//笔记 //双指针 //用法一: /* 把a[A,B,B,A,A,A,B,A] 变成 a[A,A,A,A,A,B,B,B]的形式 设置两个指针,一个从数组的左部开始找A类数,一个从数组的右部开始找B类数 当左部为A类,指针继续向后移动,指针不动,看右部,右部为B类,指针向前移动,否则 交换左右指针的值,左指针++,右指针--; 当左指针>=右指针则排序完毕; */ //用法二 /* 把nums[0,1,2,2,1,0,0,1,2] 变成nums[0,0,0,1,1,1,2,2,2]的形式 设置两个指针 l=0, r=nums.length-1 for (int i = 0; i <= r; i++) { // 从头到尾一边扫描 //如果发现当前元素==0;则和nums[l]交换,l++,i++;表示已经把0存在了头部,接下来nums[l]准备接收下一个0; //如果发现当前元素==2;则和nums[r]交换,r--,i++;表示已经把2存在了尾部,接下来nums[r]准备接收下一个2; //当i>r时说明遍历结束(r+1--nums.length-1全为2) //当nums[i]==0&&nums[l]==2时,需要把0放到num[l],2放到nums[r]中,即i与nums[i]与nums[l]交换完,i保持不变 i--,后有for循环对其++ 实现i不变,再与其nums[r]交换 //当nums[i]==0&&i==l时,此时按上面的方法处理会导致l>i 我们原先的思想类似与左右两边两条蛇,中间是我们的数组,i每次++,值为0被左边的蛇吃掉; 为2被右边吃,值为1不变;但l>i意味这i的指向在蛇的肚子里,即不符合我们的条件,处理方法是当i==l时,i++;及避免出现l>i if(nums[i]==0){ int temp=nums[i]; nums[i]=nums[l]; nums[l]=temp; if(i==l){ } else {i--;} l++; } else if(nums[i]==2){ int temp=nums[i]; nums[i]=nums[r]; nums[r--]=temp; i--; } } } //如果nums中不止有0,1,2则考虑先把左右两端先排好,在处理子问题 // */ //用法三 /* 找数组中两数之和等于具体值; 数组:nums[1,7,3,4,5,5,6,8,4,9], target=8; 问题:找nums[i],nums[j]使得之和等与target(每个数字只能使用一次) 方法:1.先将数组排好序 复杂度O(nlog(n)); 2.设置指针l,r分别从头和尾遍历,当l>r时遍历结束 3.当nums[l]+nums[r]>target 说明值需要减小;即r--; 当nums[l]+nums[r]<target 说明值需要增大;即l++; 当nums[l]+nums[r]==target 说明找到了;l++;r--;看是否还有其他满足的值 时间复杂度为O(n) 总的时间复杂度为O(nlog(n))+O(n)=O(nlog(n)); */ //用法四 /* 找单链表的中间值 设first,slow都等于链表的头节点, first每次走两步,slow每次走一步,当first.next==null或这first==null则slow即为中间节点, 数组的中间节点:nums.length/2 */
07-18
835
09-07
1168