每日5题Day6 - LeetCode 26 - 30

每一步向前都是向自己的梦想更近一步,坚持不懈,勇往直前!

第一题:26. 删除有序数组中的重复项 - 力扣(LeetCode)

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length == 1){
            return 1;
        }
        int slow = 0;
        for(int fast = 1; fast < nums.length; fast++){
            //快慢指针
            if(nums[fast] != nums[fast - 1]){
                slow++;
                nums[slow] = nums[fast];
            }
        }
        return slow + 1;
    }
}

第二题:27. 移除元素 - 力扣(LeetCode)

class Solution {
    public int removeElement(int[] nums, int val) {
        int l = 0;
        for(int r = 0; r < nums.length; r++){
            //这比上一题还简单... 快慢指针
            if(nums[r] != val){
                nums[l] = nums[r];
                l++;
            }
        }
        return l;
    }
}

第三题:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

class Solution {
    public int strStr(String haystack, String needle) {
        if (haystack == null || needle == null || needle.length() == 0) {
            return -1;
        }
        int[] lps = computeLPSArray(needle);
        int i = 0, j = 0;
        while (i < haystack.length()) {
            if (needle.charAt(j) == haystack.charAt(i)) {
                i++;
                j++;
            }
            if (j == needle.length()) {
                return i - j;
            }
            if (i < haystack.length() && needle.charAt(j) != haystack.charAt(i)) {
                if (j != 0) {
                    j = lps[j - 1];
                } else {
                    i = i + 1;
                }
            }
        }
        return -1;
    }
    private int[] computeLPSArray(String pattern) {
        //KMP算法
        int length = pattern.length();
        int[] lps = new int[length];
        int i = 1, j = 0;
        lps[0] = 0; // lps[0] 总是0
        while (i < length) {
            if (pattern.charAt(i) == pattern.charAt(j)) {
                lps[i] = j + 1;
                i++;
                j++;
            } else {
                if (j != 0) {
                    j = lps[j - 1];
                } else {
                    lps[i] = 0;
                    i++;
                }
            }
        }
        return lps;
    }
}

第四题:29. 两数相除 - 力扣(LeetCode)

class Solution {
    static final int MAX = Integer.MAX_VALUE;
    static final int MIN = Integer.MIN_VALUE;

    public int divide(int dividend, int divisor) {
        // 溢出情况
        if (dividend == MIN && divisor == -1) {
            return MAX;
        }

        // 记录结果的符号
        int sign = -1;
        if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
            sign = 1;
        }

        // 全部转换成负数,防止溢出
        dividend = dividend > 0 ? -dividend : dividend;
        divisor = divisor > 0 ? -divisor : divisor;

        int ans = 0;

        // 倍乘法,注意都是负数了,比较的时候与正数相反
        // 简单点理解,就是每次减去除数的 2^x 倍数,剩下的部分继续按这样的规则继续
        while (dividend <= divisor) {
            int tmp = divisor, count = 1;
            // 这里注意不要写成 tmp + tmp >= dividend,这样写加法有可能会溢出导致死循环
            while (tmp >= dividend - tmp) {
                // tmp 和 count 每次增加一倍,所以叫倍增
                tmp += tmp;
                count += count;
            }
            // 被除数减去除数的 2^x 倍数做为新的被除数
            dividend -= tmp;
            // count 即 2^x
            ans += count;
        }

        return sign < 0 ? -ans : ans;
    }
}

 第五题:30. 串联所有单词的子串 - 力扣(LeetCode)

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> res = new ArrayList<Integer>();
        int m = words.length, n = words[0].length(), ls = s.length();
        
        // 遍历可能的起始位置
        for (int i = 0; i < n; i++) {
            // 如果剩余字符串长度小于总单词长度,跳出循环
            if (i + m * n > ls) {
                break;
            }
            // 用于存储单词出现次数的映射
            Map<String, Integer> differ = new HashMap<String, Integer>();
            // 计算子串中每个单词的出现次数
            for (int j = 0; j < m; j++) {
                String word = s.substring(i + j * n, i + (j + 1) * n);
                differ.put(word, differ.getOrDefault(word, 0) + 1);
            }
            // 减少words数组中每个单词的计数
            for (String word : words) {
                differ.put(word, differ.getOrDefault(word, 0) - 1);
                if (differ.get(word) == 0) {
                    differ.remove(word);
                }
            }
            // 滑动窗口检查子串
            for (int start = i; start < ls - m * n + 1; start += n) {
                // 移动窗口时调整映射
                if (start != i) {
                    String word = s.substring(start + (m - 1) * n, start + m * n);
                    differ.put(word, differ.getOrDefault(word, 0) + 1);
                    if (differ.get(word) == 0) {
                        differ.remove(word);
                    }
                    word = s.substring(start - n, start);
                    differ.put(word, differ.getOrDefault(word, 0) - 1);
                    if (differ.get(word) == 0) {
                        differ.remove(word);
                    }
                }
                // 如果映射为空,表示子串中包含了所有单词
                if (differ.isEmpty()) {
                    res.add(start);
                }
            }
        }
        return res;
    }
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别看了真C不了一点

打赏者皆为义父

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值