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;
}
}