Leetcode(680回文串、88归并、141快慢指针)

Leetcode 680

题目描述:给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例一:

输入: "aba"
输出: True

示例二:

输入: "abca"
输出: True
解释: 你可以删除c字符。

思路:

双指针思想,分别从字符串头和尾进行依次遍历和比较。

增设删除标记判断是否使用过删除机会,遇到不等情况,则先判断删除标记,后选择删除后继续遍历或者返回不能成为回文字符串的结论。

踩坑点:

有一种情况:两个元素不相等时,且无论删除左边元素或是删除右边元素,都满足可以继续遍历的要求。例如"…cu…cu…"情况。

这时需要判断一下删除左边的或者右边的元素。故使用左右两个删除标记,始终规定先删除左边元素,后删除右边元素。

实现代码如下:

public class Lc680 {
    public static void main(String[] args) {
        String s = "aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga";
        System.out.println(validPalindrome(s));
    }

    public static boolean validPalindrome(String s) {
        char[] character = s.toCharArray();
        int i = 0;
        int j = character.length - 1;
        boolean isRFirst = false,isLFirst=false;
        while (i < j) {
            if (character[i] == character[j]) {
                i++;
                j--;
            } else if (!isLFirst) {
                i++;
                isLFirst = true;
            }else if(!isRFirst){
                i--;
                j--;
                isRFirst = true;
            }
            else return false;
        }
        return true;
    }
}

查看题解后,发现递归解法很妙,简洁的同时不会遇到上述坑点。

public boolean validPalindrome(String s) {
    for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
        if (s.charAt(i) != s.charAt(j)) {
            return isPalindrome(s, i, j - 1) || isPalindrome(s, i + 1, j);
        }
    }
    return true;
}

private boolean isPalindrome(String s, int i, int j) {
    while (i < j) {
        if (s.charAt(i++) != s.charAt(j--)) {
            return false;
        }
    }
    return true;
}


Leetcode 88

题目描述:给你两个有序整数数组 nums1nums2,请你将 nums2 合并到 nums1 中*,*使 nums1 成为一个有序数组。m,n分别是两个数组的元素数量。

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出: 
[1,2,2,3,5,6]

思路:

典型的归并排序。同时应用双指针的思想,与前者不同的是,前者双指针分别从头尾开始进行遍历。但此问题双指针分别从两个数组的头到尾进行遍历。

实现代码如下:

 public class Lc88 {
    public static void main(String[] args) {
        int[] nums1 = new int[]{1, 2, 3, 0, 0, 0};
        int[] nums2 = new int[]{2, 5, 6};
        merge(nums1, 3, nums2, nums2.length);
        System.out.println(Arrays.toString(nums1));
    }

    public static void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] temp = new int[m + n];
        int i = 0;
        int j = 0;
        int k = 0;
        while (i < m && j < n) {
            if (nums1[i] < nums2[j]) {
                temp[k++] = nums1[i++];

            } else if (nums1[i] > nums2[j]) {
                temp[k++] = nums2[j++];

            } else {
                temp[k] = nums1[i++];
                temp[k + 1] = nums2[j++];
                k += 2;
            }
        }
        if (i < m) {
            while (i < m) {
                temp[k++] = nums1[i++];

            }
        }
        if (j < n) {
            while (j < n) {
                temp[k++] = nums2[j++];
            }
        }
        for (int d = 0; d < (m + n); d++) {
            nums1[d] = temp[d];
        }
    }
}

提交后看题解,发现可以调库。/(ㄒoㄒ)/~~


Leetcode 141

题目描述:为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

思路:

双指针思想。但与之前不同的是,此问题需要用快慢双指针,即一个快指针和一个慢指针来求解。一个指针移动慢,一个指针移动快,如果存在环,那么这两个指针一定会相遇。

public class Lc141 {
    public static void main(String[] args) {
        ListNode node1 = new ListNode(3);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(0);
        ListNode node4 = new ListNode(-4);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node2;
        System.out.println(hasCycle(node1));
    }

    public static boolean hasCycle(ListNode head) {

        if (head == null) return false;
        ListNode p = head;
        ListNode q = head.next;
        while (q != null && (q.next) != null) {
            if (p == q) return true;
            p = p.next;
            q = q.next.next;
        }
        return false;
    }
}
class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
        next = null;
    }
}

题解中还有哈希表的解法,设置一个记录是否访问过该节点的标记数组,遍历整个链表,如果存在哈希冲突,则说明形成了环。

解法如下:

public boolean hasCycle(ListNode head) {
Set nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/linked-list-cycle/solution/huan-xing-lian-biao-by-leetcode/
来源:力扣(LeetCode)


总结:双指针的用法层出不穷,头尾指针、快慢指针等等,在不同的问题求解时灵活使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值