Qi

Cogito ergo sum

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.demo.s17;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 电话号码的字母组合
* 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
*
* 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public List<String> letterCombinations(String digits) {

List<String> combinations = new ArrayList<String>();
if (digits.length() == 0) {
return combinations;
}
Map<Character, String> phoneMap = new HashMap<Character, String>() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
return combinations;
}

public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {
if (index == digits.length()) {
combinations.add(combination.toString());
} else {
char digit = digits.charAt(index);
String letters = phoneMap.get(digit);
int lettersCount = letters.length();
for (int i = 0; i < lettersCount; i++) {
combination.append(letters.charAt(i));
backtrack(combinations, phoneMap, digits, index + 1, combination);
combination.deleteCharAt(index);
}
}
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.demo.s169;

import java.util.HashMap;
import java.util.Map;

/**
* 给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
*
* 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
*
*  
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/majority-element
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
private Map<Integer, Integer> countNums(int[] nums) {
Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
for (int num : nums) {
if (!counts.containsKey(num)) {
counts.put(num, 1);
} else {
counts.put(num, counts.get(num) + 1);
}
}
return counts;
}

public int majorityElement(int[] nums) {
Map<Integer, Integer> counts = countNums(nums);

Map.Entry<Integer, Integer> majorityEntry = null;
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {
majorityEntry = entry;
}
}

return majorityEntry.getKey();
}

}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.demo.s165;

/**
* 给你两个版本号 version1 和 version2 ,请你比较它们。
*
* 版本号由一个或多个修订号组成,各修订号由一个 '.' 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。
*
* 比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。
*
* 返回规则如下:
*
* 如果 version1 > version2 返回 1,
* 如果 version1 < version2 返回 -1,
* 除此之外返回 0。
*  
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/compare-version-numbers
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int compareVersion(String version1, String version2) {
String[] v1 = version1.split("\\.");
String[] v2 = version2.split("\\.");

for (int i = 0; i < v1.length||i<v2.length; ++i) {
int x = 0, y = 0;
if (i < v1.length) {
x = Integer.parseInt(v1[i]);
}
if (i < v2.length) {
y = Integer.parseInt(v2[i]);
}
if (x > y) {
return 1;
}
if (x < y) {
return -1;
}
}
return 0;
}


}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.demo.s160;

/**
* Definition for singly-linked list.

*/
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.demo.s16;

import java.util.Arrays;

/**
* 最接近的三数之和
* 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
*
* 返回这三个数的和。
*
* 假定每组输入只存在恰好一个解。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/3sum-closest
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int n = nums.length;
int best = 10000000;

// 枚举 a
for (int i = 0; i < n; ++i) {
// 保证和上一次枚举的元素不相等
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// 使用双指针枚举 b 和 c
int j = i + 1, k = n - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
// 如果和为 target 直接返回答案
if (sum == target) {
return target;
}
// 根据差值的绝对值来更新答案
if (Math.abs(sum - target) < Math.abs(best - target)) {
best = sum;
}
if (sum > target) {
// 如果和大于 target,移动 c 对应的指针
int k0 = k - 1;
// 移动到下一个不相等的元素
while (j < k0 && nums[k0] == nums[k]) {
--k0;
}
k = k0;
} else {
// 如果和小于 target,移动 b 对应的指针
int j0 = j + 1;
// 移动到下一个不相等的元素
while (j0 < k && nums[j0] == nums[j]) {
++j0;
}
j = j0;
}
}
}
return best;


}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.demo.s155;

import java.util.Stack;

/**
* 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
*
* 实现 MinStack 类:
*
* MinStack() 初始化堆栈对象。
* void push(int val) 将元素val推入堆栈。
* void pop() 删除堆栈顶部的元素。
* int top() 获取堆栈顶部的元素。
* int getMin() 获取堆栈中的最小元素。
*  
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/min-stack
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
class MinStack {

//数据
private Stack<Integer> data;
//最小栈
private Stack<Integer> minStack;
public MinStack() {
data = new Stack();
minStack = new Stack();
}

public void push(int val) {
data.push(val);
if(minStack.size() == 0) {
minStack.push(val);
} else {
//最小值存栈顶,如果不是最小,取栈顶的最小值再存一次,保证pop后 最小值还在栈顶
minStack.push(Math.min(val, minStack.peek()));
}
}

public void pop() {
minStack.pop();
data.pop();
}

public int top() {
return data.peek();
}

public int getMin() {
return minStack.peek();
}
}

public class Solution {}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.demo.s151;

import java.util.Deque;
import java.util.LinkedList;

/**
* 给你一个字符串 s ,颠倒字符串中 单词 的顺序。
*
* 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
*
* 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
*
* 注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/reverse-words-in-a-string
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public String reverseWords(String s) {
StringBuilder sb = trimSpaces(s);

// 翻转字符串
reverse(sb, 0, sb.length() - 1);

// 翻转每个单词
reverseEachWord(sb);

return sb.toString();
}

public StringBuilder trimSpaces(String s) {
int left = 0, right = s.length() - 1;
// 去掉字符串开头的空白字符
while (left <= right && s.charAt(left) == ' ') {
++left;
}

// 去掉字符串末尾的空白字符
while (left <= right && s.charAt(right) == ' ') {
--right;
}

// 将字符串间多余的空白字符去除
StringBuilder sb = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);

if (c != ' ') {
sb.append(c);
} else if (sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}

++left;
}
return sb;
}

public void reverse(StringBuilder sb, int left, int right) {
while (left < right) {
char tmp = sb.charAt(left);
sb.setCharAt(left++, sb.charAt(right));
sb.setCharAt(right--, tmp);
}
}

public void reverseEachWord(StringBuilder sb) {
int n = sb.length();
int start = 0, end = 0;

while (start < n) {
// 循环至单词的末尾
while (end < n && sb.charAt(end) != ' ') {
++end;
}
// 翻转单词
reverse(sb, start, end - 1);
// 更新start,去找下一个单词
start = end + 1;
++end;
}
}

}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.demo.s15;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* 三数之和
* 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
*
* 注意:答案中不可以包含重复的三元组。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/3sum
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//结果list
List ret = new ArrayList();
//判断入参
if(nums.length < 3) return ret;
//排序数据,方便设置左右边界 遍历
Arrays.sort(nums);
//先定义一个元素遍历,作为三个中最小的一个值
for(int i = 0 ;i< nums.length-2; i++) {
//判断终止条件
if(nums[i] > 0) return ret;
//忽略到相同的值
if(i> 0 && nums[i] == nums[i-1]) continue;
//第二个元素 取区间左边界
int L = i +1;
//第三个元素 取区间右边界
int R = nums.length - 1;
//如果左右边界重合 则停止
while(L < R) {
//如果三数和为0
if(nums[i] + nums[L] + nums[R] == 0) {
//记录三个数
List numbers = new ArrayList();
numbers.add(nums[i]);
numbers.add(nums[L]);
numbers.add(nums[R]);
ret.add(numbers);
//基于已有的和为0 左右移动边界 寻找其他的记录
while(L< R && (nums[L] == nums[L+1])) {
//忽略相同的数值 左边界右移
L++;
}
while(R > L && nums[R] == nums[R-1]) {
//忽略相同的数值 右边界左移
R--;
}
//移动左右边界
L++;
R--;
} else if(nums[i] + nums[L] + nums[R] < 0) {
// 和小于0 左边界右移
L++;
} else {
// 和大于0 右边界左移
R--;
}
}
}
return ret;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.demo.s148;

/**
* 排序链表
* 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
*/
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
public class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}

public ListNode sortList(ListNode head, ListNode tail) {
if(head == null) {
return head;
}
if(head.next == tail) {
head.next = null;
return head;
}

ListNode fast = head;
ListNode slow = head;
while(fast != tail) {
fast = fast.next;
slow = slow.next;
if(fast != tail) {
fast = fast.next;
}
}
ListNode mid = slow;
ListNode m = sortList(head, mid);
ListNode n = sortList(mid, tail);
return mergeList(m, n);
}
public ListNode mergeList(ListNode head, ListNode tail) {
ListNode dum = new ListNode(0);
ListNode tmp1 = head;
ListNode tmp2 = tail;
ListNode tmp = dum;
while(tmp1 != null && tmp2 != null) {
if(tmp1.val < tmp2.val) {
tmp.next = tmp1;
tmp1 = tmp1.next;
} else {
tmp.next = tmp2;
tmp2 = tmp2.next;
}
tmp = tmp.next;
}
if(tmp1 != null) {
tmp.next = tmp1;
}
if(tmp2 != null) {
tmp.next = tmp2;
}
return dum.next;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.demo.s147;

/**
* 排序链表
* 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表
*/
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
public class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}

public ListNode sortList(ListNode head, ListNode tail) {
if(head == null) {
return head;
}
if(head.next == tail) {
head.next = null;
return head;
}

ListNode fast = head;
ListNode slow = head;
while(fast != tail) {
fast = fast.next;
slow = slow.next;
if(fast != tail) {
fast = fast.next;
}
}
ListNode mid = slow;
ListNode m = sortList(head, mid);
ListNode n = sortList(mid, tail);
return mergeList(m, n);
}
public ListNode mergeList(ListNode head, ListNode tail) {
ListNode dum = new ListNode(0);
ListNode tmp1 = head;
ListNode tmp2 = tail;
ListNode tmp = dum;
while(tmp1 != null && tmp2 != null) {
if(tmp1.val < tmp2.val) {
tmp.next = tmp1;
tmp1 = tmp1.next;
} else {
tmp.next = tmp2;
tmp2 = tmp2.next;
}
tmp = tmp.next;
}
if(tmp1 != null) {
tmp.next = tmp1;
}
if(tmp2 != null) {
tmp.next = tmp2;
}
return dum.next;
}

}
0%