重拾刷题路01

2022-02-13

78.Subsets(Medium)

https://leetcode.com/problems/subsets/

给出不含重复数字的数组,返回所有不含重复元素的子集。

(1)级联(通过增加一个数字,生成新的集合)

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        result.add(new ArrayList<>());
        
        for (int num : nums) {
            List<List<Integer>> subList =  new ArrayList<>();
            for (List<Integer> list : result) {
                List<Integer> newList = new ArrayList<>();
                newList.addAll(list); // 复制现有结果
                newList.add(num); // 把新的数字加进去
                subList.add(newList);
            }
            result.addAll(subList); // 把本次加完数字产生的集合加到结果中
        }
        
        return result;
    }
}

 (2)递归回溯法

使用回溯法,和人的解题思路类似,先固定第一个数字,然后选第二个数字,以此类推。

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        for (int size = 0; size <= nums.length; size++) {
            recursive(0, size, new ArrayList<>(), nums, result);
        }
        return result;
    }
    
    public void recursive(int startPos, int resSize, List<Integer> list, int[] nums, List<List<Integer>> result) {
        if (list.size() == resSize) {
            result.add(new ArrayList<>(list));
            return;
        }
        for (int pos = startPos; pos < nums.length; pos++) {
            list.add(nums[pos]);
            recursive(pos + 1, resSize, list, nums, result);
            list.remove(list.size() - 1);
        }
    }
}

 67.Add Binary(Easy)

https://leetcode.com/problems/add-binary/

注意补零,由于StringBuilder只能补在最后,所以要先reverse,再补零,再reverse回来。

注意进位的逻辑。

class Solution {
    public String addBinary(String a, String b) {
        StringBuilder result = new StringBuilder();
        int lengthA = a.length();
        int lengthB = b.length();
        int length = 0;
        // 把短的字符串前面补0
        if (lengthA > lengthB) {
            length = lengthA;
            StringBuilder sb = new StringBuilder(b).reverse();
            for (int i = 1; i <= (lengthA - lengthB); i++) {
                sb.append('0');
            }
            b = sb.reverse().toString();
        } else if (lengthB > lengthA) {
            length = lengthB;
            StringBuilder sb = new StringBuilder(a).reverse();
            for (int i = 1; i <= (lengthB - lengthA); i++) {
                sb.append('0');
            }
            a = sb.reverse().toString();
        } else {
            length = lengthA;
        }
        // 是否要进位
        boolean plus = false;
        for (int pos = length - 1; pos >= 0; pos--) {
            char charA = a.charAt(pos);
            char charB = b.charAt(pos);
            char charResult;
            if (charA == '0' && charB == '0') {
                charResult = plus ? '1' : '0';
                plus = false;
            } else if (charA == '1' && charB == '1') {
                charResult = plus ? '1' : '0';
                plus = true;
            } else {
                charResult = plus ? '0' : '1';
            }
            result.append(charResult);
            if (pos == 0 && plus) { // 最后还有进位需要加一位
                result.append('1');
            }
        }
        return result.reverse().toString();
    }
}

228. Summary Ranges(Easy)

https://leetcode.com/problems/summary-ranges/

fast和slow两个指针即可。这里用了两个while循环,但是实际的时间复杂度还是O(n)。

class Solution {
    public List<String> summaryRanges(int[] nums) {
        List<String> result = new ArrayList<>();
        if (nums.length == 0) {
            return result;
        }
        int slow = 0;
        int fast = 0;
        while (slow < nums.length && fast < nums.length) {
            String str = String.valueOf(nums[slow]);
            while (fast < nums.length - 1 && nums[fast + 1] == nums[fast] + 1) {
                fast++;                
            }
            if (fast != slow) {
                str = str + "->" + nums[fast];
            }
            slow = fast + 1;
            fast = slow;
            result.add(str);
        }
        return result;
    }
}

2022-02-20

14. Longest Common Prefix(Easy)

https://leetcode.com/problems/longest-common-prefix/

垂直扫描循环,一共两层

public String longestCommonPrefix(String[] strs) {
        StringBuilder commonPrefix = new StringBuilder();
        int index = 0;
        boolean end = false;
        while (true) {
            String commonChar = null;
            for (String str : strs) {
                if (index == str.length()) {
                    end = true;
                    break;
                }
                if (commonChar != null && !String.valueOf(str.charAt(index)).equals(commonChar)) {
                    end = true;
                    break;
                }
                commonChar = String.valueOf(str.charAt(index));
            }
            if (end) {
                return commonPrefix.toString();
            }
            commonPrefix.append(commonChar);
            index++;
        }
    }

263. Ugly Number(Easy)

https://leetcode.com/problems/ugly-number/

用2,3,5分别去除,最后的结果,大于1不是丑数,等于1是丑数。注意:题目里说了整数,但是test case里有负数,需要直接返回false!

public boolean isUgly(int n) {
        if (n <= 0) {
            return false;
        }
        int[] uglyPrimeFactors = new int[]{2, 3, 5};
        for (int primeFactor : uglyPrimeFactors) {
            int remainder = 0;
            while (n > 1 && remainder == 0) {
                remainder = n % primeFactor;
                if (remainder == 0) {
                    n = n / primeFactor;
                }
            }
        }
        return n == 1;
    }

168. Excel Sheet Column Title(Easy)

https://leetcode.com/problems/excel-sheet-column-title/

类似一个26进制,但要注意余数为0的情况,需要补上Z,同时商减1:

public String convertToTitle(int columnNumber) {
        StringBuilder title = new StringBuilder();
        while (columnNumber > 0) {
            int remainder = columnNumber % 26;
            columnNumber = columnNumber / 26;
            if (remainder == 0) {
                title.append('Z');
                columnNumber--;
                continue;
            }
            char subTitle = (char) (remainder + 64);
            title.append(subTitle);
        }
        return title.reverse().toString();
    }

2022-02-21

26. Remove Duplicates from Sorted Array(Easy)

https://leetcode.com/problems/remove-duplicates-from-sorted-array/

非递减数组去重,要求不使用额外空间。

(1)超时的方法,时间复杂度太大,因为要双重循环:

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums.length == 1) {
            return 1;
        }
        int slow = 0;
        int fast = 1;
        while (fast < nums.length && nums[slow] <= nums[fast]) {
            if (nums[slow] == nums[fast]) {
                moveNum2Last(nums, fast);
            }
            if (nums[fast] != nums[slow]) {
                slow++;
                fast++;
            }
        }
        return fast;
    }

    public void moveNum2Last(int[] nums, int index) {
        for (int i = index; i < nums.length - 1; i++) {
            replace(nums, i, i + 1);
        }
    }

    public void replace(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

(2)先把重复的替换,然后再把替换的统一挪到最后

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums.length == 1) {
            return 1;
        }
        int slow = 0;
        while (slow < nums.length - 1) {
            int fast = slow + 1;
            while (fast < nums.length && nums[fast] == nums[slow]) {
                nums[fast] = 999; // 把重复的换成999
                fast++;
            }
            slow = fast;
        }
        // 把999挪到后面
        int index999 = 0;
        int indexNot999 = 0;
        while (index999 < nums.length && indexNot999 < nums.length) {
            if (nums[index999] != 999) {
                index999++; // 找到第一个999的下标
                continue;
            }
            indexNot999 = index999 + 1; // 后面第一个不是999的下标
            while (indexNot999 < nums.length && nums[indexNot999] == 999) {
                indexNot999++;
            }
            if (indexNot999 < nums.length) {
                replace(nums, index999, indexNot999);
            }
        }
        int result = 0;
        while (result < nums.length && nums[result] != 999) {
            result++;
        }
        return result;
    }

    public void replace(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

(3)i负责循环,currentPos为要替换数字的下标。

class Solution {
    public int removeDuplicates(int[] nums) {
        int currentPos = 0; // 去重后面的第一个数字的下标
        int currentNum=Integer.MIN_VALUE; // 要替换的数字
        for(int i= 0; i<nums.length; i++) {
            if(nums[i] != currentNum) { // 不相等时,说明找到了下一个更大的数字
                nums[currentPos] = nums[i];
                currentNum = nums[i];
                currentPos++;
            }
        }
        return currentPos;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值