今天的内容是双指针。
双指针
双指针一般应用于数组,链表,比如用于数组的头尾指针,判断链表带环问题的快慢指针,两个指针的移动速度不一定能够相同。
双指针种类:
1.有用在两个数组中的,遍历比较这两个数组的。
2.同一个数组中同向追赶指针
3.同一个数组中相向最终相遇的指针。
4.链表的快慢指针
题解
思路:先遍历字符串找到那个ch字符,找不到直接返回源字符串。然后用双指针一个指向开头,一个指向ch,两个指针相向移动,交换字符即可。
char * reversePrefix(char * word, char ch){
int i =0;
int start = 0;
for(i = 0;word[i];i++)
{
if(word[i]==ch)
{
break;
}
}
if(word[i]=='\0')
{
return word;
}
while(start < i)
{
char tmp = word[start];
word[start] = word[i];
word[i] = tmp;
start++;
i--;
}
return word;
}
思路:用双指针遍历字符串,如果左右都是字母就交换,如果左边是字符,右边不是就–right;反之++left,如果两边都不是字母就–rigth;++left
char * reverseOnlyLetters(char * s){
int len = strlen(s);
int left = 0;
int right = len-1;
while(left<right)
{
if(isalpha(s[left])&&isalpha(s[right]))
{
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
else if(isalpha(s[left]))
{
right--;
}
else if(isalpha(s[right]))
{
left++;
}
else
{
left++;
right--;
}
}
return s;
}
排序+二分_思路:先对这个heaters进行排序,然后枚举每个房子,去heaters中找到小于等于该房子的最大的供暖器heaters下标记为uleft,也就是从左边,离着这个房子最近的供暖期位置,然后右边里这个房子最近的供暖器下标为uright,计算出左距离,右距离,然后取最小值,然后将最小半径,与ans比较,最小半径里面的最大半径,就是答案。
二分查找时有两个特殊情况,当heaters[0]都>find时,返回-1,让左距离失效,即为INTMAX,这时候右距离就时heaters[0]到房屋的最小距离。当返回的uleft = heaterssize-1(当作n-1),时uleft = n,这时候如果计算右距离就会越界,也就是最右边的供暖器都在房子的左边,右距离为负数,记作INTMAX,然后左距离此时即使最小距离。
int cmp(const void* str1,const void* str2)
{
return *(int*)str1 - *(int*)str2;
}
int Binary(int* heaters,int heatersSize,int find)
{
int max = 0;
int left = 0;
int right = heatersSize-1;
if(heaters[left]>find)
{
return -1;//返回左下标为-1(无效坐标)右坐标为0,因为这样子右距离为正的,否则返回0的话左距离为负会出错。
}
while(left<=right)
{
int mid = (left+right)>>1;
if(heaters[mid]<=find)
{
max = mid;
left = mid+1;
}
else
{
right = mid-1;
}
}
return max;
}
int findRadius(int* houses, int housesSize, int* heaters, int heatersSize){
int max = 0;
int ans = 0;
int leftdistance = 0;
int rightdistance = 0;
qsort(heaters,heatersSize,sizeof(int),cmp);
for(int i =0;i<housesSize;i++)
{
int find = houses[i];
int uleft = Binary(heaters,heatersSize,find);
int uright = uleft+1;//当left为n-1的时候,右距离失效,防止越界。
leftdistance = uleft<0?INT_MAX:houses[i]-heaters[uleft];
rightdistance = uright>=heatersSize?INT_MAX:heaters[uright]-houses[i];
max = leftdistance<rightdistance?leftdistance:rightdistance;
ans = max>ans?max:ans;
}
return ans;
}
排序+二分思路:先将b数组排序,然后遍历a数组到b数组内进行二分查找,找到一个小于等于target的最大值的下标,返回,(特殊情况,b的最小元素都比a大,就返回-1,)然后计算左差值和右差值,最后比较两个差值的大小,取最小的,与ans比较,最终返回小的哪一个就是最小差值。
注意:这里求差值可能会超过int的整形,求之前先将被减数强制转换为long long就可以了。
int cmp(const void*str1,const void* str2)
{
return *(int*)str1 - *(int*)str2;
}
int Binary(int* b,int bSize,int target)
{
int ans = bSize-1;
int left = 0;
int right = bSize-1;
if(b[left]>target)
{
return -1;
}
while(left<=right)
{
int mid = (right-left)/2+left;
if(b[mid]<=target)
{
ans = mid;
left = mid+1;
}
else
{
right = mid-1;
}
}
return ans;
}
int smallestDifference(int* a, int aSize, int* b, int bSize){
int uleft = 0;
int uright = 0;
long long subleft = 0;
long long subright = 0;
int ans = INT_MAX;
int min = 0;
qsort(b,bSize,sizeof(int),cmp);
for(int i =0;i<aSize;i++)
{
uleft = Binary(b,bSize,a[i]);
uright = uleft+1;
subleft = uleft<0?INT_MAX:a[i]-b[uleft];
subright = uright>=bSize?INT_MAX:(long long)b[uright] - a[i];
min = subleft<subright?subleft:subright;
ans = ans<min?ans:min;
}
return ans;
}