-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLeetCode2.txt
266 lines (219 loc) · 7.93 KB
/
LeetCode2.txt
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
数组
1.两数之和
nums = [a,b,c,d,e] target = n
如果 nums中有两个数和等于target,则返回[index1,index2]
解法:一遍hash,在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。
如果它存在,那我们已经找到了对应解,并立即将其返回。
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
2.两数相加
l1: 3->0->7 l2:4->5->8 求307+458得到的新链表
解法:
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
3.无重复字符最大字串
解法:如果 s[j]s[j] 在 [i, j)[i,j) 范围内有与 j'重复的字符,我们不需要逐渐增加 i 。
我们可以直接跳过 [i,j′] 范围内的所有元素,并将 i 变为 j' + 1
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}
}
5.最长回文子串
解法:中心扩展法
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
7.反转整数
解法:弹出和推入数字&溢出前进行检查
class Solution {
public int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
}
9.回文数
解法:反转一半数字(先考虑临界情况,所有负数都不是回文数,再把数字%10得最后一位,再/10缩一位)
public class Solution {
public bool IsPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,如果数字的最后一位是 0,为了使该数字为回文,
// 则其第一位数字也应该是 0
// 只有 0 满足这一属性
if(x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while(x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x == revertedNumber || x == revertedNumber/10;
}
}
19.删除链表的倒数第n个节点
解法:2个指针,第一个先走n+1步,第二个开始走,当第一个到最后时,第二个到达第n个
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
// Advances first pointer so that the gap between first and second is n nodes apart
for (int i = 1; i <= n + 1; i++) {
first = first.next;
}
// Move first to the end, maintaining the gap
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
206.反转链表
public class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)
return null;
ListNode pReverseHead = null;
ListNode pNode = head;
ListNode pPrev = null;
while(pNode != null){
ListNode pNext = pNode.next;
if(pNext == null){
pReverseHead = pNode;
}
pNode.next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReverseHead;
}
}
92.指定位置链表逆序
public ListNode reverseBetween(ListNode head, int m, int n) {
if (head == null || head.next == null) return head;
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode prev = dummy, next = head.next;
// set two pointer
while (--m > 0) {
prev = prev.next;
}
while (--n > 0) {
next = next.next;
}
// reverse linklist between prev and next
ListNode last = prev.next;
ListNode curr = last.next;
while (curr != next) {
last.next = curr.next;
curr.next = prev.next;
prev.next = curr;
curr = last.next;
}
return dummy.next;
}
198.动态规划
每个阶段只有一个状态,使用递推。
题目要求相邻的两个不能同时取,同时要求和最大,那采用的方式隔一个取一个了。
dp[i]表示在第i的位置,取得的和是多少。而dp[i] = max(dp[i-2]+nums[i],dp[i-1]),所以只要对初始状态进行初始化,然后迭代所有的nums[i],最后就可以使和最大。
public int rob(int[] num) {
if (num.length == 0) return 0;
int prepre = 0;
int pre = num[0];
for (int i = 1; i < num.length; i++) {
int cur = Math.max(prepre + num[i], pre);
prepre = pre;
pre = cur;
}
return pre;
}
213.房子围城一个圈,最后一间房子和第一间是邻居
思路:最优解就变成 第1座房子到第n-1座房子能抢的最多的钱 或者 第2座房子到第n座房子能抢的钱了。
public int rob(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
if(nums.length == 1)
return nums[0];
int length = nums.length;
//最优解就变成 第1座房子到第n-1座房子能抢的最多的钱 或者 第2座房子到第n座房子能抢的钱了
return Math.max(robBetween(nums, 0, length-2),robBetween(nums, 1, length-1));
}
public int robBetween(int[] nums, int start, int end){
int prepre = 0;
int pre = nums[start];
for(int i = start+1; i <= end; i++){
int cur = Math.max(prepre+nums[i],pre);
prepre = pre;
pre = cur;
}
return pre;
}