-
Notifications
You must be signed in to change notification settings - Fork 2
/
LeetCode-01.md
476 lines (372 loc) · 12.8 KB
/
LeetCode-01.md
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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# LeetCode算法练习-字符串篇
### 反转字符串
请编写一个函数,其功能是将输入的字符串反转过来。
**示例**
```java
输入:s = "hello"
返回:"olleh"
```
**思路**
```java
1、string 转char[]数组 然后依序遍历
2、位运算 a^=b 交换位置 ab交换位置 我示例代码给这个思路的 效率会高一些
```
**代码**
```java
class Solution {
public String reverseString(String s) {
if (null == s || s.length() == 0) return s;
char[] ch = s.toCharArray();//字符串转换成字符数组
int len = s.length();
for (int i = 0; i < len / 2; i++) {
ch[i] ^= ch[len - 1 - i];//位运算交换位置
ch[len - 1 - i] ^= ch[i];
ch[i] ^= ch[len - 1 - i];
}
return new String(ch);
}
}
```
### 反转整数
给定一个 32 位有符号整数,将整数中的数字进行反转。
**示例**
```java
输入: 123
输出: 321
输入: -123
输出: -321
输入: 120
输出: 21
//假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。
//根据这个假设,如果反转后的整数溢出,则返回 0。
```
**思路**
```java
1、判断符号
2、反转数字
3、去0 并转成数字
4、如果抛异常就返回0
```
**代码**
```java
class Solution {
public int reverse(int x) {
boolean isF = x < 0;
String value = String.valueOf(Math.abs(x));
char[] chars = value.toCharArray();
int len = chars.length;
for (int i = 0; i < len / 2; i++) {
chars[i] ^= chars[len - 1 - i];//位运算交换位置
chars[len - 1 - i] ^= chars[i];
chars[i] ^= chars[len - 1 - i];
}
value = new String(chars);
if (chars[0] == 0) value = value.substring(1);
try {
if (isF) return -1 * Integer.parseInt(value);
return Integer.parseInt(value);
} catch (Exception e) {
return 0;
}
}
}
```
### 字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
**示例**
```java
s = "leetcode"
返回 0.
s = "loveleetcode",
返回 2.
//您可以假定该字符串只包含小写字母。
```
**思路**
```java
//建立Hash表 排除重复选项 再遍历hash表 判断是否有唯一字符
```
**代码**
```java
class Solution {
public int firstUniqChar(String s) {
int index = -1;
if (s == null) return index;
Map<Character, Integer> chMap = new LinkedHashMap<>();
for (char c : s.toCharArray()) {
if (!chMap.containsKey(c)) {
chMap.put(c, 1);
} else {
chMap.put(c, chMap.get(c) + 1);
}
}
for (Character key : chMap.keySet()) {
if (chMap.get(key) == 1) return s.indexOf(String.valueOf(key));
}
return index;
}
}
```
### 有效的字母异位词
给定两个字符串 *s* 和 *t* ,编写一个函数来判断 *t* 是否是 *s* 的一个字母异位词。
**示例**
```java
s = "anagram",t = "nagaram",返回 true
s = "rat",t = "car",返回 false
注意:假定字符串只包含小写字母。
提升难度:
输入的字符串包含 unicode 字符怎么办?你能能否调整你的解法来适应这种情况?
```
**思路**
```jav
1.将两个字符串转换为字符串数组
2.排序数组
3.判断两个数组的元素是否相同(用系统自带的方法了,你也可以遍历,其实系统方法内部实现原理也不一样是遍历)
```
**代码**
```java
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
// if (s.length() == 1 && t.length() == 1) return s.equals(t);
char[] sch = s.toCharArray();
char[] tch = t.toCharArray();
Arrays.sort(sch);
Arrays.sort(tch);
return Arrays.equals(sch, tch);
}
}
```
### 验证回文字符串
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
**说明:**本题中,我们将空字符串定义为有效的回文串。
**示例**
```java
输入: "A man, a plan, a canal: Panama"
输出: true
输入: "race a car"
输出: false
```
**思路**
```java
1.替换字符串中的所有空格 如果替换完的字符串为空 则返回true 空格为有效的回文串
2.提出除英文字符和数字以外所有的特殊字符并将大写转换为小写
3.翻转字符串
4.判断翻转后的字符串与翻转前的字符串是否相等
```
**代码**
```java
class Solution {
public boolean isPalindrome(String s) {
if (s.length() == 1) return true;
String p = s.replace(" ", "");
if (p.equals("")) return true;
s = p.replaceAll("[^a-z0-9A-Z]", "").toLowerCase();
char[] ch = s.toCharArray();
int len = s.length();
for (int i = 0; i < len / 2; i++) {
ch[i] ^= ch[len - 1 - i];//位运算交换位置
ch[len - 1 - i] ^= ch[i];
ch[i] ^= ch[len - 1 - i];
}
return s.equals(new String(ch));
}
}
//另外一种写法
class Solution {
public boolean isPalindrome(String s) {
if (s.length() == 1) return true;
if (s.replace(" ", "").equals("")) return true;
s = s.replaceAll("[^a-z0-9A-Z]", "");
return s.equalsIgnoreCase(new StringBuffer(s).reverse().toString());
}
}
```
### 字符串转整数(atoi)
实现 `atoi`,将字符串转为整数。
在找到第一个非空字符之前,需要移除掉字符串中的空格字符。如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即为整数的值。如果第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
字符串可以在形成整数的字符后面包括多余的字符,这些字符可以被忽略,它们对于函数没有影响。
当字符串中的第一个非空字符序列不是个有效的整数;或字符串为空;或字符串仅包含空白字符时,则不进行转换。
若函数不能执行有效的转换,返回 0。
**说明:**
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。如果数值超过可表示的范围,则返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
**示例**
```java
输入: "42"
输出: 42
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
```
**思路**
```java
去除字符串两端空字符
拦截输入字符只是+或者-的字符
拦截首字符是非数字字符直接返回0
遍历判断是否为数字字符遇到非数字即跳出循环
```
**代码**
```java
class Solution {
public int myAtoi(String str) {
str = str.trim();
if (str.length() == 0) return 0;
if (str.equals("+") || str.equals("-")) return 0;
String first = String.valueOf(str.charAt(0));
if (!first.equals("+")
&& !first.equals("-") && !Character.isDigit(str.charAt(0))) return 0;
boolean isF = first.equals("-");
if (first.equals("+") || isF) str = str.substring(1);
char[] ch = str.toCharArray();
String s = "";
p:
for (char c : ch) {
if (Character.isDigit(c)) s += c;
else break p;
}
if (s.length() == 0) return 0;
try {
if (isF) return -1 * Integer.parseInt(s);
return Integer.parseInt(s);
} catch (Exception e) {
if (isF) return Integer.MIN_VALUE;
return Integer.MAX_VALUE;
}
}
}
```
### 实现strStr()
实现 [strStr()](https://baike.baidu.com/item/strstr/811469) 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 **-1**。
**示例**
```java
输入: haystack = "hello", needle = "ll"
输出: 2
输入: haystack = "aaaaa", needle = "bba"
输出: -1
```
**注意**:当`needle`是空字符串时,应当返回`0`
**思路**
```java
这道算法其实是让我们明白 string类内 indexOf() 方法的原理
当然你使用 indexOf() 方法可以快速完成,但是最好还是知道下原理最好
原理解释:首先会查找子字符串的头字符在此字符串中第一次出现的位置,再以此位置的下一个位置开始,然后将子字符串的字符依次和此字符串中字符进行比较,如果全部相等,则返回这个头字符在此字符串中的位置;如果有不相等的,则继续在剩下的字符串中查找,继续进行上面的过程,直到查找到子字符串或没有找到返回-1为止。
```
**代码**
```java
class Solution {
public int strStr(String haystack, String needle) {
if (needle == null || needle.length() == 0) return 0;
return haystack.indexOf(needle);
}
}
```
### 数数并说
报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
```
1. 1
2. 11
3. 21
4. 1211
5. 111221
```
**示例**
```JAVA
输入: 1
输出: "1"
输入: 4
输出: "1211"
```
**思路**
```java
"数数并说,搞清楚什么时候合并数字什么时候不合并数字就可以了。"
1.并说:超过1个相同的数字连在一起时,并说,也就是"几个几"
2.不并说:前后数字不同时,不并说,需要单说,也就是"1个几"
```
**代码**
```java
class Solution {
public String countAndSay(int n) {
if (n <= 0) return "-1";
String result = "1";
for (int i = 1; i < n; i++) {
StringBuilder builder = new StringBuilder();
int index = 0;
while (index < result.length()) {
// 记录值
char val = result.charAt(index);
// 记录连续位数
int count = 0;
// 查找连续位数,碰到不相同的数字时停止。
while (index < result.length() && result.charAt(index) == val) {
index++;
count++;
}
// 追加连续位数到结果中
builder.append(String.valueOf(count));
// 追加连续位数的值到结果中
builder.append(val);
}
result = builder.toString();
}
return result;
}
}
```
### 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 `""`。
**示例**
```java
输入: ["flower","flow","flight"]
输出: "fl"
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
//说明:所有输入只包含小写字母 a-z 。
```
**思路**
```java
1.获取字符串数组中字符串最小的串
2.使用最小串遍历定位字符串数组中相同串的长度
```
**代码**
```java
class Solution {
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
int minLen = Integer.MAX_VALUE;
for (String str : strs) {
minLen = Math.min(minLen, str.length());
}
int low = 0;
int high = minLen;
while (low <= high) {///注意是 <=
int middle = (low + high) / 2;
if (isCommonPrefix(strs, middle))
low = middle + 1;
else
high = middle - 1;
}
return strs[0].substring(0, (low + high) / 2);
}
private boolean isCommonPrefix(String[] strs, int len) {
String str1 = strs[0].substring(0, len);
for (int i = 0; i < strs.length; i++) {
if (!strs[i].startsWith(str1))
return false;
}
return true;
}
}
```