目录
前言:本章将会介绍三道来自leetcode上的经典题目,涉及到的思路主:双指针
1:剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)
2: 977. 有序数组的平方 - 力扣(LeetCode)
题目描述:
给我们一个字符串,和给一个整数n要求我们将字符串中前n个字符旋转到字符串后面去。
下面我来介绍这道题的解法:-->
解法1:暴力解法 时间复杂度为o(n^2)
思路:我们首先写出左旋1个字符的代码,然后在执行n次就行了。
左旋一个字符的思路:我们先将首元素用tmp变量将它给保存起来,让后将首元素后面的元素移动到前面来,然后再将tmp放到最后一个位置。
图:
代码:
while(n--)
{
char tmp=*s;
int i =1;
for(i=1;i<strlen(s);i++)
{
s[i-1]=s[i];//挪动元素
}
//最后一个字符改为原来的第一个
s[i-1]=tmp;
}
但是暴力解法在leetcode跑步过去,因为时间复杂度太高了。
所以我们得换一种解法。
解法2:3步逆序字符串法 时间复杂度为O(N) 空间O(1)
思路:我们先将字符串中前n个字符给逆序,在将n后面的字符串给逆序,最后在整体逆序就行了。原地修改字符串.
在写代码的时候我们得注意字符串下标最大为n-1。
代码:
void reverse(char** pps,int left,int right)
{
while(left<right)
{
char tmp=(*pps)[left];
(*pps)[left]=(*pps)[right];
(*pps)[right]=tmp;
left++;
right--;
}
}
char* reverseLeftWords(char* s, int n){
reverse(&s,0,n-1);//逆置前n个
reverse(&s,n,strlen(s)-1);//逆置n后面
reverse(&s,0,strlen(s)-1);//整体逆置
return s;
}
解法三:切割+合并 时间O(n) 空间O(n)
思路:将前n个字符给拿出来,且增加一个'\0'字符,剩下的字符也存储起来,最后将两个合并就行,后n个字符放在前面,前n个拼接在后面,就能够实现。
代码:
char* reverseLeftWords(char* s, int n){
n=n%(strlen(s)+1);
char* ret1=(char*)malloc(sizeof(char)*(n+1));//放要旋转的字符还得放'\0'
char* ret2=(char*)malloc(sizeof(char)*(strlen(s)+1));
//先放要旋转的字符串
int i=0;
int j=0;
for(i=0;i<n;i++)
{
ret1[j]=s[i];
j++;
}
ret1[j]='\0';
j=0;
for(i=n;i<strlen(s);i++)
{
ret2[j]=s[i];
j++;
}
int k =0;
while(ret1[k]!='\0')
{
ret2[j++]=ret1[k++];
}
ret2[j]='\0';
return ret2;
}
总结:在这三个方法中,第二种方法毫无疑问是最好的,但也是最难想到的。
本题的分享完毕,让我们进入下一题。
2: 977. 有序数组的平方 - 力扣(LeetCode) 方法1:排序加遍历
思路:我们先将数组中的元素全部平方,然后在加个快速排序就可以解决了。 时间复杂度:O(nlogn) 代码实现:
//时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int left=0;
int right=numsSize-1;
while(left<=right)
{
if(nums[left]*nums[left]>nums[right]*nums[right])
{
int tmp=nums[right];
nums[right--]=nums[left]*nums[left];
nums[left]=tmp;
}
else
{
nums[right--]=nums[right]*nums[right];
}
}
* returnSize=numsSize;
return nums;
}
图:
方法2: 因为我们知道这个数组是一个有序数组,所以越往两边,平方的值越大,所以我们采用双指针的方法来进行求解,将大的元素给放在最后。
图:
代码:
//时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
//新开辟的一块空间,
int* ret=(int*)malloc(sizeof(int)*numsSize);
int i =numsSize-1;
int left=0;
int right=numsSize-1;
while(left<=right)
{
if(nums[left]<0)
nums[left]=-nums[left];
if(nums[left]>nums[right])
{
ret[i--]=nums[left]*nums[left];
left++;
}
else
{
ret[i--]=nums[right]*nums[right];
right--;
}
}
* returnSize=numsSize;
return ret;
}
本题分享完毕--_--
3:27. 移除元素 - 力扣(LeetCode)
移除相同的元素:这题我们直接讲解双指针法,暴力解法我们就不讲了。
双指针法:我们使用两个指针1个指针用来遍历整个数组的元素,另外一个指针用来修改数组中的元素。
代码:
int removeElement(int* nums, int numsSize, int val){
int fast=0;
int slow=0;
while(fast<numsSize)
{
if(nums[fast]!=val)
{
nums[slow]=nums[fast];
slow++;
}
fast++;
}
return slow;
}
本章经典算法题结束,如果你觉得对你有用的话,可以点个赞哦!
如果有什么错误的地方,欢迎大佬来指点。