Leecode——2021.04.19

27. 移除元素

class Solution {
    public int removeElement(int[] nums, int val) {
        int len = nums.length;
        for(int i = len - 1; i >= 0; i--){
            if(nums[i] == val){
                move(nums, i, len);
                len--;
            }
        }
        return len;
    }


    // 移动逻辑
    public void move(int[] nums, int pos, int len){
        for(int i = pos + 1; i < len; i++){
            nums[i - 1] = nums[i];
        }
    }
}

双指针

26. 删除有序数组中的重复项

class Solution {
    public int removeDuplicates(int[] nums) {
        int left = 1;
        int right = 1;
        int n = nums.length;
        if(n == 0 || n == 1){
            return n;
        }
        
        int pre = nums[0];// 前一个点的位置
        while(right < n){
            if(nums[right] == pre){
                right++;
            }
            else{
                nums[left++] = nums[right];
                pre = nums[right];
                right++;
            }
        }
        return left;
    }
}

Leecode大神给出的对于删除重复项的通用解法。————k表示可以保留多少个重复的项

class Solution {
    public int removeDuplicates(int[] nums) {   
        return process(nums, 1);
    }
    int process(int[] nums, int k) {
        int idx = 0; 
        for (int x : nums) {
            if (idx < k || nums[idx - k] != x) nums[idx++] = x;
        }
        return idx;
    }
}

回文系列

面试题 01.04. 回文排列

class Solution {
    public boolean canPermutePalindrome(String s) {
        int n = s.length();
        if(n == 0 || n == 1){
            return true;
        }
        // 这个题不是给的就是回文串,而是将这个回文串打乱了,看这个给定的字符串是否由那个回文串打乱得到的
        // 利用HashMap的方式
        Map<Character, Integer>map = new HashMap<>();
        for(int i = 0; i < n; i++){
            int num = map.getOrDefault(s.charAt(i), 0);
            map.put(s.charAt(i), num+1);
        }
        // 如果map集合里面的元素value值符合都是2的倍数或者说只有一个的value不是2的倍数那么就是回文串打乱来的
        int cnt = 0;
        for(Map.Entry<Character, Integer> entry: map.entrySet()){
            if(entry.getValue() % 2 == 1){
                cnt++;
            }
        }

        if(cnt > 1){
            return false;
        }
        else{
            return true;
        }
    }
}

9. 回文数

给定一个正数,判断是否是一个回文数

// 反转部分字符串然后比较。从后往前截取

class Solution {
    public boolean isPalindrome(int x) {
        if(x < 0 || (x % 10 == 0 && x != 0)){
            // 负数不可能是
            // 120这种最后一位是0,但是不是0的不是回文数
            return false;
        }

        int reverseNum = 0;
        while(reverseNum < x){
            reverseNum = reverseNum * 10 + x % 10;
            x = x / 10;
            // 不断的获取最后一位数,然后相加
        }

        // 分为了奇数和偶数两种情况
        // eg:12321  这时候reverseNum = 123
        return x == reverseNum || x == reverseNum / 10;
    }
}

// 全部翻转。转化为String。利用StringBuilder来反转

class Solution {
    public boolean isPalindrome(int x) {
        if(x < 0){
            return false;
        }
        String str = String.valueOf(x);
        StringBuilder sb = new StringBuilder(str);
        if(str.equals(sb.reverse().toString())){
            return true;
        }else{
            return false;
        }
    }
}

125. 验证回文串

// 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

// 首位双指针法。碰到不是字母或者数字的跳过即可

class Solution {
    public boolean isPalindrome(String s) {
        // 将大写字母转化为小写字母

        // 然后按照回文串来判断即可.注意一点就是,双指针碰到一个非字母或者数字的时候直接跳过
        int n = s.length();
        s = s.toLowerCase();// 转换为小写
        int left = 0, right = n - 1;
        while(left < right){
            if( ( Character.isDigit(s.charAt(left)) ||
                    Character.isAlphabetic(s.charAt(left)) ) &&
                    ( Character.isDigit(s.charAt(right)) ||

                            Character.isAlphabetic(s.charAt(right))
                    )
            )
            {
                // left right所指向的字符是数字或者字母的时候才进行比较
                if(s.charAt(left) == s.charAt(right)){
                    left++;
                    right--;
                }else{
                    return false;
                }
            }
            else if(

                    (Character.isDigit(s.charAt(left)) ||
                            Character.isAlphabetic(s.charAt(left)) ) &&

                            (!Character.isAlphabetic(s.charAt(right)) &&
                                    !Character.isDigit(s.charAt(right))
                            )){
                // 左边是数字或字母、右边不是
                right--;
            }
            else if(
                    (Character.isDigit(s.charAt(right)) ||
                            Character.isAlphabetic(s.charAt(right)) ) &&

                            (!Character.isAlphabetic(s.charAt(left)) &&
                                    !Character.isDigit(s.charAt(left))

                            )){
                // 右边是数字或字母、左边不是
                left++;
            }
            else{
                // 都不是数字或者字母
                left++;
                right--;
            }
        }
        return true;

    }


}

234. 回文链表

// 高端做法:找到链表后半段的起点。反转后半段链表。然后和前半段链表比较。——Leeocde官方

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){
            return true;
        }
        ListNode firstHalfEnd = getFirstHalf(head);
        ListNode afterreverseHalfStart = reverseList(firstHalfEnd.next);

        // 比较两者是否是回文
        ListNode pre = head;
        ListNode end = afterreverseHalfStart;
        boolean flag = true;
        while(flag && end != null){
            if(pre.val != end.val){
                flag = false;
            }
            pre = pre.next;
            end = end.next;
        }

        // 将链表转换为原来的结构
        firstHalfEnd.next = reverseList(afterreverseHalfStart);

        return flag;
    }

    // 反转链表
    public ListNode reverseList(ListNode head){
        ListNode s = head;
        ListNode pre = null;
        while(s != null){
            ListNode tmp = s.next;
            s.next = pre;
            pre = s;
            s = tmp;
        }
        return pre;
    }

    // 获取前半段链表的尾节点。
    // 如果是奇数的话,中间节点是尾节点
    public ListNode getFirstHalf(ListNode head) {
        ListNode low = head;
        ListNode high = head;
        while(high.next != null && high.next.next != null){
            // 如何找到。慢指针每次走一格。快指针走两个。当快指针走完的时候low正好指在前半段的末尾
            low = low.next;
            high = high.next.next;
        }
        return low;
    }
    
}

// 暴力做法,利用数组或者字符串存储链表的val。然后就变成了基本的回文数的判断了

posted @ 2021-04-19 21:22  codeDJH  阅读(69)  评论(0编辑  收藏  举报