[Leetcode学习-c++&java]Remove Duplicates IN String&Array&List

介绍:

去掉集合中,相邻重复元素的问题,无论集合是 string(string 是 char 数组来的) array list 都有相似思路,就是用三指针来解决,所以都放到一块了,首先是 list 的指针处理,引出了对 array string 这两种集合的处理思路。


List:

问题1:Remove Duplicates from Sorted List II

难度:medium

说明:

下面题目的解题思路都是从这题来的,给出一个 list 输入,然后将 list 中有数值重复两次以上的所有节点删除掉, list 是有序的。

题目连接:https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/

输入范围:

  • The number of nodes in the list is in the range [0, 300].
  • -100 <= Node.val <= 100
  • The list is guaranteed to be sorted in ascending order.

输入案例:

Example 1:
Input: head = [1,2,3,3,4,4,5]
Output: [1,2,5]

Example 2:
Input: head = [1,1,1,2,3]
Output: [2,3]

我的代码:

这里的话,首先想到两个指针,一个前一个后就能够对比节点数值,找出重复了两次的节点。但是依然缺少一个在重复节点之前那个节点的指针,所以再加多一个拼接指针,指向 list 的拼接末尾,然后再来一个 dummy 隐藏的头节点,存放删除后 list 的头结点,一共三指针就可以处理了。

然后还需要一个标记 flag 记录 避免一前一后指针遇到 两组 重复节点, 拼接指针就傻傻地往后走了。

Java:

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(-101), next = dummy, pre = dummy; // 隐藏节点开始出发
        dummy.next = head;
        boolean flag = false; // 用一个记录标记
        while(head != null) {
            if(head.val == pre.val) {
                pre = head;
                head = head.next;
                flag = false;
            } else {
                if(flag) next = next.next; // 相当于第二次没找到重复节点,才让拼接指针往后移动
                pre = head;
                next.next = pre;
                head = head.next;
                flag = true;
            }
        }
        if(!flag) next.next = null;
        return dummy.next;
    }
}

C++:

扫描二维码关注公众号,回复: 12506196 查看本文章
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode *dummy = new ListNode(-101), *next = dummy, *pre = dummy;
        bool flag = false;
        dummy -> next = head;
        while(head != nullptr) {
            if(head -> val == pre -> val) {
                pre = head;
                head = head -> next;
                flag = false;
            } else {
                pre = head;
                head = head -> next;
                if(flag) next = next-> next;
                next -> next = pre;
                flag = true;
            }
        }
        if(!flag) next -> next = nullptr;
        return dummy -> next;
    }
};

问题2:Remove Duplicates from Sorted List

难度:easy

说明:

只需要删除 list 中重复节点的其一一个之外的节点,留下一个重复节点,简单很多,就保留第一个就行。

题目连接:https://leetcode.com/problems/remove-duplicates-from-sorted-list/

输入范围:

  • The number of nodes in the list is in the range [0, 300].
  • -100 <= Node.val <= 100
  • The list is guaranteed to be sorted in ascending order.

输入案例:

Input: head = [1,1,2]
Output: [1,2]

我的代码:

很简单,留一个的话,我把他后面都删了就行。

Java:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode current = head;
        while (current != null && current.next != null) 
            if (current.next.val == current.val) current.next = current.next.next;
            else current = current.next;
        return head;
    }
}

C++:

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* root = head;
        if(head != nullptr)
            while(head->next != nullptr) 
                if(head->next->val == head->val) head->next = head->next->next;
                else head = head->next;
        return root;
    }
};

Array:

问题1:Remove Duplicates from Sorted Array II

难度:medium

说明:

和 list 第一题思路一样,三指针,加上重复标记,返回时候注意下标就可以了,把数组中重复的都去掉,然后返回一个下标索引,下标相当于 从 0 ~ N 是你去掉了 重复元素之后的数组元素。

题目连接:https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/

输入范围:

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums is sorted in ascending order.
Example 1:
Input: nums = [1,1,1,2,2,3]
Output: 5, nums = [1,1,2,2,3]
Explanation: Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively. It doesn't matter what you leave beyond the returned length.

Example 2:
Input: nums = [0,0,1,1,1,1,2,3,3]
Output: 7, nums = [0,0,1,1,2,3,3]
Explanation: Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively. It doesn't matter what values are set beyond the returned length.

我的代码:

这里特别的是,它会检查输入的数组改动,而不接受你去创建一个新数组,不过有了 list 第一题的思路就不怕了。

Java:

class Solution {
    public int removeDuplicates(int[] nums) {
        int cur = 0, pre = 0, next = 1, len = nums.length;
        boolean dupFlag = false;
        while(next < len) {
            if(nums[next] == nums[pre]) {
                if(dupFlag) {
                    next ++;
                    pre ++;
                } else {
                    next ++;
                    pre ++;
                    nums[++ cur] = nums[pre];
                    dupFlag = true;
                }
            } else {
                next ++;
                pre ++;
                nums[++ cur] = nums[pre];
                dupFlag = false;
            }
        }
        return cur + 1;
    }
}

C++:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int cur = 0, pre = 0, next = 1, len = nums.size(), dupFlag = 0;
        while(next < len) {
            if(nums[pre] == nums[next]) {
                if(!dupFlag) {
                    nums[++ cur] = nums[next];
                    dupFlag = 1;
                }
            } else {
                nums[++ cur] = nums[next];
                dupFlag = 0;
            }
            next ++; pre ++;
        }
        return cur + 1;
    }
};

问题2:Remove Duplicates from Sorted Array

难度:easy

说明:

和 list 第二题思路一样,只去掉一个很简单。

题目连接:https://leetcode.com/problems/remove-duplicates-from-sorted-array/submissions/

输入范围:

  • 0 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums is sorted in ascending order.

输入案例:

Example 1:
Input: nums = [1,1,2]
Output: 2, nums = [1,2]
Explanation: Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the returned length.

Example 2:
Input: nums = [0,0,1,1,1,2,2,3,3,4]
Output: 5, nums = [0,1,2,3,4]
Explanation: Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. It doesn't matter what values are set beyond the returned length.

我的代码:

一样解法。

Java:

class Solution {
    public int removeDuplicates(int[] nums) {
        int pre = 0, next = 1, len = nums.length;
        while(next < len)
            if(nums[pre] == nums[next]) next ++;
            else nums[++pre] = nums[next ++];
        return len == 0 ? 0 : 1 + pre;
    }
}

C++:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int pre = 0, next = 1, len = nums.size();
        while(next < len)
            if(nums[pre] == nums[next]) next ++;
            else nums[++ pre] = nums[next ++];
        return len == 0 ? 0 : pre + 1;
    }
};

String:

问题1:Remove Duplicates from Sorted Array 

难度:easy

说明:

这题相对不一样,不过依然可以用指针想法处理,题目要求去掉所有重复的一对的相邻字符,而且每去掉一对,合并一次字符串,再进行判断相邻重复的一对字符。

题目连接:https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/

输入范围:

  • 1 <= s.length <= 10^5
  • 2 <= k <= 10^4
  • s only contains lower case English letters.

输入案例:

Input: "abbaca"
Output: "ca"
Explanation: 
For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move.  The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca".

我的代码:

虽然有明显不同,但是依然可以通过指针来判断,因为输入只有小写字母,所以可以用其他字符作为无效字符的标记。

用两个一前一后指针判断是否有重复的一对字符,然后 把该处重复的一对字符标记为 0,标记之后,需要移动两个指针到另一个相邻位置:

1、如果 pre(前) != 0 ,往前找到第一个 不是 0 的字符,next 往后移动一个。

2、如果 pre == 0 ,跳到 next 前一个字符,next 往后移动两个。

要注意,pre 往前往后移动时候都要判断是否到了边界或者遇到了 0 无效字符。

Java:

class Solution {
    public String removeDuplicates(String S) {
        int cur = 0, pre = 0, next = 1, len = S.length();
        char[] chs = S.toCharArray();
        StringBuilder builder = new StringBuilder();
        while(next < len) {
            if(chs[next] == chs[pre]) {
                chs[pre] = chs[next] = 0;
                if(pre != 0) { // 情况 1
                    next ++;
                    while(pre != 0 && chs[-- pre] == 0); // 跳过无效字符
                    if(pre == 0 && chs[pre] == 0) {
                        next ++;
                        pre = next - 1;
                    }
                } else { // 情况2
                    next += 2;
                    pre = next - 1;
                }
            } else {
                next ++;
                while(chs[++ pre] == 0); // 跳过无效字符
            }
        }
        for(char ch : chs) {
            if(ch != 0) builder.append(ch);
        }
        return builder.toString();
    }
}

C++:

暂无。

问题2:Remove All Adjacent Duplicates in String II

难度:medium

说明:

这题要求去掉 K 个相邻的重复字符,每去掉 K 个,合并一次字符串,再进行判断相邻重复 K 个字符。

题目连接:https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/

输入范围:

  • 1 <= s.length <= 10^5
  • 2 <= k <= 10^4
  • s only contains lower case English letters.

输入案例:

Example 1:
Input: s = "abcd", k = 2
Output: "abcd"
Explanation: There's nothing to delete.

Example 2:
Input: s = "deeedbbcccbdaa", k = 3
Output: "aa"
Explanation: 
First delete "eee" and "ccc", get "ddbbbdaa"
Then delete "bbb", get "dddaa"
Finally delete "ddd", get "aa"

Example 3:
Input: s = "pbbcggttciiippooaais", k = 2
Output: "ps"

我的代码:

一样用双指针,多家排除 0 的 pre 移动操作就行,另外多一个 count 计数,当 count 是 指定的重复数就开始标记无效字符就行。

class Solution {
    public String removeDuplicates(String s, int k) {
        int pre = 0, next = 1, back, len = s.length(), count = 0, kd = k - 2;
        char[] chs = s.toCharArray();
        StringBuilder builder = new StringBuilder();
        while(next < len) {
            if(chs[pre] == chs[next]) {
                if(count == kd) {
                    chs[next] = 0;
                    int pred = k - 1;
                    while(pred -- > 0) { // 前指针回撤都得排除 0
                        while(chs[pre] == 0) pre --;
                        chs[pre] = 0;
                    }
                    next ++;
                    while(pre > 0 && chs[pre] == 0) pre --;
                    if(pre < 0 || chs[pre] == 0) {
                        next ++;
                        pre = next - 1;
                    }
                    back = pre - 1;
                    count = 0;
                    while(back >= 0) { // 回计指针回撤都得排除 0
                        if(chs[back] == 0) back --;
                        else
                            if(chs[back] == chs[pre]) {
                                count ++;
                                while(-- back >= 0 && chs[back] == 0);
                            }
                            else break;
                    }
                } else { // 前指针回撤都得排除 0
                    next ++;
                    while(pre < next && chs[++ pre] == 0);
                    count ++;
                }
            } else { // 前指针回撤都得排除 0
                next ++;
                while(pre < next && chs[++ pre] == 0);
                count = 0;
            }
        }
        for(char ch : chs) if(ch != 0) builder.append(ch);
        return builder.toString();
    }
}

C++:

暂无

猜你喜欢

转载自blog.csdn.net/qq_28033719/article/details/112271918