第二天(双指针)
有序数组的平方
两种方法:第一种暴力=.=没得讲.
第二种:
其实我们把负数进行了平方后负数部分就是降序排列我们的正数部分是升序排列不过怎样都是有序的,我们可以使用类似于归并排序的思想.不过归并排序的思想要求我们两部分都应该是升序或者降序的所以我们将负数部分倒着读取就可以完成归并排序的一次过程了.
int* sortedSquares(int* nums, int numsSize, int* returnSize)
{
int lin = -1;
for(int i = 0;i<numsSize;i++)
{
if(nums[i] < 0)
{
lin = i;
}
nums[i] = nums[i]*nums[i];
}
int* ret = (int*)malloc(sizeof(int)*numsSize);
*returnSize = numsSize;
//用lin分成两部分
//lin<0时直接nums内全为正确排序
if(lin<0)
{
for(int i = 0;i<numsSize;i++)
{
ret[i] = nums[i];
}
return ret;
}
//lin>=0是用归并排序即可
int begin1 = 0;
int end1 = lin;
int begin2 = lin+1;
int end2 = numsSize-1;
int i = 0;
while(begin1 <= end1 && begin2<=end2)
{
if(nums[end1]>nums[begin2])
{
ret[i] = nums[begin2];
begin2++;
i++;
}
else if(nums[end1]<=nums[begin2])
{
ret[i] = nums[end1];
end1--;
i++;
}
}
while(begin1<=end1)
{
ret[i] = nums[end1];
end1--;
i++;
}
while(begin2<=end2)
{
ret[i] = nums[begin2];
begin2++;
i++;
}
return ret;
}
轮转数组
次次做次次不会=.= 不过这样的题比较偏背一些=.=
既然次次做次次不会,那我就把这道题的两个思路都顺一遍.
方法一
再次之前我们可以先将k %= n;因为当k>n的时候轮转其实都是循环.
此方法是经验所得,所以可以背一背=.=
- 逆置 0~(n-k-1)之间的元素
- 逆置
(n-k)~(n-1)
的位置 - 逆置所有元素.
(记忆法: 只需记住第一步0~(n-k-1)然后逆序第一步没有逆序到的部分再逆序所有即可)
即可使数组向右轮转k个位置.
代码如下图
void reverse(int* nums,int left,int right)
{
while (left < right)
{
int ret = nums[left];
nums[left] = nums[right];
nums[right] = ret;
left++;
right--;
}
}
void rotate(int* nums, int numsSize, int k)
{
k %= numsSize;
reverse(nums,0,numsSize-k-1);
reverse(nums,numsSize-k,numsSize-1);
reverse(nums,0,numsSize-1);
}
方法二(使用额外数组)
这种方法就很好理解了.
我们将数组向右轮转的时候其实每个元素轮转后的下标都是与k有关的都是(i+k)%(n)—其中i是元素下标
非常好理解,i+k本身就是轮转后的下标位置但是有可能会超出数组空间所以我们要加以限制及%n使用n的原因是因为我们的得到的下标值最大应该是n-1所以%n即可.
代码如下:
void rotate(int* nums, int numsSize, int k)
{
k%=numsSize;
int* tmp = (int*)malloc(sizeof(int)*numsSize);
assert(tmp);
for(int i =0;i<numsSize;i++)
{
tmp[(i+k)%numsSize] = nums[i];
}
for(int i =0;i<numsSize;i++)
{
nums[i] = tmp [i];
}
free(tmp);
}