【双指针算法应用举例】反转链表、二分查找、有序数组的平方等

总结 :双指针法的循环条件

 while (left <= right) {
     
 }
1. 704. 二分查找 注意必须是升序或者降序的数组才可以 mid=(left+right)/2
2.977. 有序数组的平方

数组其实是有序的, 只不过负数平方之后可能成为最大数了。

那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。

//双指针法
    public int[] sortedSquares(int[] nums) {
        int[] result = new int[nums.length];
        int left = 0;
        int right = nums.length - 1;
        int index = nums.length - 1;
        //数组本来就是有序 所以平方后的最大值 不是由最左边得来 就是最右边得来
        while (left <= right) {
            int a = nums[left] * nums[left];
            int b = nums[right] * nums[right];
            if (a < b) {
                result[index] =b;
                right--;
                index--;
            }else {
                result[index]=a;
                left++;
                index--;
            }
        }
        return result;
    }
3. 移除元素

public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length-1;
        while (left <= right) {
            if (nums[left] == val) {
                nums[left] = nums[right];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }
4.19. 删除链表的倒数第 N 个结点

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

//双指针法 两个指针一个指向哑节点 一个指向首节点

注意:(一般leetcode给的题目head就是第一个节点,我们通常所说的头节点就是指dummy节点)

  • fast和slow同时指向head时候,当fast最后==null时,slow指向的是待删除节点;
  • 为了更方便我们设置哑节点dummy,slow开始指向dummy,fast仍指向head,这样最后slow指向的就是待删除节点的前一个节点;
//双指针法 两个指针一个指向哑节点 一个指向首节点
    //first先走n下,停下来,然后两个指针一起走,等到first为null时候,此时second指向的就是待删除节点的前一个节点
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy=new ListNode(0,head);
        ListNode first=head;
        ListNode second=dummy;
        for(int i=0;i<n;i++){
            first=first.next;
        }
        while(first!=null){
            second=second.next;
            first=first.next;
        }
        second.next=second.next.next;
        ListNode newHead=dummy.next;
        return newHead;
    
    }
5.344. 反转字符串 原地修改数组(前后交换即可)
6.206. 反转链表

只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表

【双指针算法应用举例】反转链表、二分查找、有序数组的平方等_第1张图片

思路:

两个节点precurr; pre初始化为null,curr初始化指向head; 然后反转,然后节点后移

public ListNode reverseList(ListNode head) {
        ListNode pre=null;
        ListNode cur=head;
        ListNode temp=null;
        while(cur!=null){
            //先保存下一个节点
            temp=cur.next;
            //再把当前节点指向pre
            cur.next=pre;
            //然后两个节点后移
            pre=cur;
            cur=temp;
        }
        //当cur指向null 此时pre指向的是末尾节点
        return pre;
    }
7.链表相交

​ 未做题。

141.环形链表1

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null && fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }
}
8.142. 环形链表 II - 力扣(LeetCode)
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode pos = head;
        Set<ListNode> visited = new HashSet<ListNode>();
        while (pos != null) {
            if (visited.contains(pos)) {
                return pos;
            } else {
                visited.add(pos);
            }
            pos = pos.next;
        }
        return null;
    }
}

 public ListNode detectCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (true) {
            if (fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;
        }
        ListNode temp = head;
        while (slow != temp) {
            slow = slow.next;
            temp = temp.next;
        }
        return temp;
    }
9.15. 三数之和 - 力扣(LeetCode)

​ 未做题

10.18. 四数之和 - 力扣(LeetCode)

​ 未做题

你可能感兴趣的:(算法学习,算法,链表,数据结构)