算法之双指针
移除元素
代码报错原因,在快指针进行判断时没有判断是否超出边界。
j<nums.length
思想:使用快慢指针,初始化两个指针都指向第一个元素
- 当快指针==val值时,快指针后移一位,循环此操作;
- 当快指针!=val时,将快指针的值赋给慢指针,快慢指针皆往后移动一位
int j=0;
int i=0;
while(j<nums.length){
while(j<nums.length&&nums[j]==val){
j++;
}
if(j<nums.length&&nums[j]!=val){
nums[i]=nums[j];
i++;
j++;
}
}
return i;
替换数字※
实现了replace的手动实现,但没有使用双指针法从后往前进行替换。
StringBuffer strB=new StringBuffer(s);
for (int i=0; i<strB.length();i++ ) {
if (strB.charAt(i) <='9'&& strB.charAt(i)>='0'){
String substring=strB.substring(i+1,strB.length());
strB.setLength(strB.length()+5);
strB.replace(i+6,strB.length(),substring);
strB.replace(i,i+6,"number");
i=i+5;
}
}
System.out.println(strB.toString());
反转字符串中的单词
双指针的思想主要指删除空格,如果不用双指针,找到需要删除的每个元素是O(n),将后面的元素往前移需要O(n),复杂度为O(n2);
用双指针为O(n),思想和移除元素相同!!
int slowIndex=0;
int fastIndex=0;
while(fastIndex<strB.length() && strB.charAt(fastIndex)==' '){
fastIndex++;
}
for(;fastIndex<strB.length();fastIndex++){
if(fastIndex>0 && strB.charAt(fastIndex) == strB.charAt(fastIndex-1) && strB.charAt(fastIndex)==' '){
continue;
}else{
strB.setCharAt(slowIndex,strB.charAt(fastIndex));
slowIndex++;
}
}
if(strB.charAt(slowIndex-1)==' '){
strB.setLength(slowIndex-1);
}else{
strB.setLength(slowIndex);
}
链表中删除第倒N个节点
报错原因:没有考虑到当N和链表节点个数相同时,此时end节点为null的情况
思路:使用快慢指针,快指针和慢指针间隔N-1个位置,当快指针到达尾节点时,慢指针=慢指针.next
查看代码
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode start=head;
ListNode end=head;
while(end !=null && n>0){
end=end.next;
n--;
}
if (end==null){
return start.next;
}
while(end.next != null){
end=end.next;
start=start.next;
}
start.next=start.next.next;
return head;
}
链表相交
报错:1、Java中求绝对值的函数Math.abs()
2、for循环的中间位置为判断是否满足该条件,满足则继续执行
3、一开始想从尾往头判断是否相等(错误思想),因为链表的指针只指向后一个
4、没有考虑存在链表为空的情况
思路:将指向长链表的指针向前移动,直到和短链表的头位置相同,然后就可以进行判断
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode tailA=headA;
ListNode tailB=headB;
if(headA== null || headB ==null){
return null;
}
int lengthA=1;
int lengthB=1;
while(tailA.next != null){
lengthA++;
tailA=tailA.next;
}
while(tailB.next != null){
lengthB++;
tailB=tailB.next;
}
tailA=headA;
tailB=headB;
for(int i=0;i<Math.abs(lengthA-lengthB);i++){
if(lengthA>lengthB){
tailA=tailA.next;
}else{
tailB=tailB.next;
}
}
while(tailA != tailB && tailA.next != null && tailB!=null){
tailA=tailA.next;
tailB=tailB.next;
}
if(tailA == tailB){
return tailA;
}
return null;
}
环形链表相交※
首先明确快慢指针相交的点不一定是入环点,但相交点一定是环内的一点。
切入点:通过快慢指针步数的两倍关系,构建等式。根据等式得:快慢指针在环内相交之后从head开始和从相交点开始一起走,再相交的点为入环点!
使用while(fast.next!=null && fast!=null)判断不为环形链表
三数相加※
首先明确思想,外层为left循环,内层循环为mid和right大小判断。相当于将left作为锚点,对于每一个left值,mid和right在left+1和nums.legth-1中移动。
确保结果不重复的切入点:在内层循环外对nums[left]和nums[left-1](必须是和-1,不能是+1)进行相等判断,若相等continue(continue执行后,for中的left++依然执行!!!!!)
在内层循环内当三数相等时,循环判断nums[mid]==nums[mid+1],若成立则mid++,right同理。
Java函数基本用法:Arrays.asList(数组):将数组转为list
list.add():向list中添加元素
总结
双指针可以用来移除和修改指定数组元素,因为数组元素不能被删除,只能被覆盖
双指针可以用来删除指定位置的链表元素,和解决链表相交的问题
双指针用来获得多数相加为指定值的情况,情况为具体值而不是在数组中的下标


浙公网安备 33010602011771号