1.合并两个有序数组 (merge)
void switch_num(int*num, int pos1, int pos2){
int a = 0;
a = num[pos1];
num[pos1] = num[pos2];
num[pos2] = a;
return;
}
int removeElement(int* nums, int numsSize, int val) {
//no need to consider the order
//switch all val to the rear
int first_Val = numsSize-1;
int pos = numsSize-1;
while(pos>=0){
if(nums[pos] == val){
switch_num(nums, first_Val, pos);
pos--;
first_Val--;
}
else{
pos--;
}
}
return first_Val+1;
}
我的思路
经典做法,不用多说,但是要记住,看到类似的算法要马上回忆起来。
2. 移除元素
我的思路
就地移除,办法是移到后面藏起来,从数组末尾开始有奇效,目前不知道为什么。
双指针法,一个用来遍历,一个用来确定放置位置。
我的算法
void switch_num(int*num, int pos1, int pos2){
int a = 0;
a = num[pos1];
num[pos1] = num[pos2];
num[pos2] = a;
return;
}
int removeElement(int* nums, int numsSize, int val) {
//no need to consider the order
//switch all val to the rear
int first_Val = numsSize-1;
int pos = numsSize-1;
while(pos>=0){
if(nums[pos] == val){
switch_num(nums, first_Val, pos);
pos--;
first_Val--;
}
else{
pos--;
}
}
return first_Val+1;
}
算法学习
int removeElement(int* nums, int numsSize, int val) {
int slow = 0, fast = 0; //一对夫妇,原本都是零起点
while (fast < numsSize) { //但是有一个跑得快,一个跑得慢
if (nums[fast] != val) { //于是跑得快的那个先去寻找共同目标
nums[slow] = nums[fast]; //如果找到了,就送给跑得慢的那个
slow++; //然后跑得慢的那个也就离目标近一点
}
fast++; //但是不管是否找得到,跑得快的那方都一直奔跑到生命的尽头
}
return slow; //最终留下跑得慢的一方
}
他的算法比我的简单,并且能够保持原来的顺序,值得学习。
3. 删除有序数组中的重复项
我的算法
int removeDuplicates(int* nums, int numsSize) {
int slow = 1, fast = 1; // first element is always needed!
while(fast < numsSize){
if(nums[fast] <= nums[slow-1]){
fast++;
}
else{
nums[slow++] = nums[fast++];
}
}
return slow;
}
学习了上一题的快慢指针,果然清晰明了多了。
4. 删除有序数组中的重复项 II
我的算法
int removeDuplicates(int* nums, int numsSize) {
//Every element has 2 chances to show up
int showup = 1;
int slow = 1, fast = 1;
while(fast < numsSize){
//Meet new, showup = 2 - 1
if(nums[fast] != nums[slow-1]){
nums[slow++] = nums[fast++];
showup = 1;
}
else{
if(showup){
nums[slow++] = nums[fast++];
showup--;
}
else{
fast++;
}
}
}
return slow;
}
我的思路
依旧是快慢指针
5. 多数元素
我的算法
int majorityElement(int* nums, int numsSize) {
int pos = 1;
int vote = nums[0];
int cnt = 1;
while(pos < numsSize){
if(nums[pos] == vote){
cnt++;
}
else{
cnt--;
}
if(cnt<0){
vote = nums[pos];
cnt = 1;
}
pos++;
}
return vote;
}
我的思路
投票法,是一个值得牢记的思路
6. 买卖股票的最佳时机
我的算法
int maxSub(int* arr, int size){
int max = -10000, this = 0;
for(int i = 0; i < size; i++){
this += arr[i];
if(this > max){
max = this;
}
if(this < 0){
this = 0;
}
}
return (max>0)?max:0;
}
int maxProfit(int* prices, int pricesSize) {
int* diff_price = malloc(sizeof(int)*pricesSize-1);
for(int i = 0; i< pricesSize-1; i++){
diff_price[i] = prices[i+1] - prices[i];
}
return maxSub(diff_price, pricesSize-1);
}
我的思路
相邻两天价格求差,然后利用最长子列和进行积分。
算法学习
一遍扫描,找到更低的价格后,把当前最好的情况和他相结合,看能不能找到更好的情况。(骑驴找马)
这道题核心在于,更低的价格不意味着能够找到更好的买家来换取更高的利润,所以要骑驴找马,之前最好的情况先记在心中,然后按着这个更低的价格来,看能不能超越之前的利润,超越了我就更新。
int maxProfit(int* prices, int pricesSize) {
int best= 0, pos = 1;
int max = prices[0], min = prices[0];
while(pos < pricesSize){
if(prices[pos] < min){
min = prices[pos];
max = min + best;
}
if(prices[pos] > max){
max = prices[pos];
best = prices[pos] - min;
}
pos++;
}
return best;
}
算法学习2
和算法学习1差不多的思路
int maxProfit(int* prices, int pricesSize) {
int min = INT_MAX, best = 0;
for(int i = 0; i < pricesSize; i++){
min = prices[i]<min?prices[i]:min;
best = prices[i]-min>best?prices[i]-min:best;
}
return best;
}
7. 最大子数组和
我的算法
int maxSubArray(int* nums, int numsSize) {
int max = -29999, this = 0;
for(int i = 0; i<numsSize; i++){
this += nums[i];
if(this > max){
max = this;
}
if(this < 0){
this = 0;
}
}
return max;
}
我的思路
非常重要的题型,一定要倒背如流。
强化思路
试试分治法