LeetCode-19-20-21

这三题均为 Easy ,合并到一起写写解题思路。

19 Remove Nth Node From End of List

概述

Remove Nth Node From End of List 即删除单向链表中从链表尾部开始的第N个节点。

分析

单向链表只能通过逐步前进才能到达指定节点,是无法在 O(1) 的时间复杂度下拿到链表的长度的,可以考虑通过一次遍历将链表明确节点节点位置与值的对应关系,之后通过链表的节点操作完成删除节点的效果。

节点位置与值的关系可以通过Hash进行存储,由于链表长度不定,预先留出数组空间的方式个人认为并不是好的选择。

解法

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
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
HashMap<Integer, ListNode> idxListMap = new HashMap<Integer, ListNode>();

ListNode it = head;
int i = 1;

for(; it != null; it = it.next, ++i) {
idxListMap.put(i, it);
}

if (idxListMap.size() == 1) {
return null;
}

if (n == 1) {
idxListMap.get(idxListMap.size() - 1).next = null;
return head;
}

if (n == idxListMap.size()) {
head = head.next;
return head;
}

if (idxListMap.containsKey(idxListMap.size() - n) && idxListMap.containsKey(idxListMap.size() - n + 2)) {
idxListMap.get(idxListMap.size() - n).next = idxListMap.get(idxListMap.size() - n + 2);
}

return head;
}
}

20 Valid Parentheses

概述

Valid Parentheses 即判断括号是否匹配。

分析

括号需要一一对应,即一个左括号,需要对应一个右括号,简单来说,在字符串遍历过程中,右括号出现之后,需要判断上一个括号是不是一个左括号,如果是一个左括号,那么说明这个括号完成了匹配。否则,说明没有完成匹配。

从数据结构上来说,是一个非常适合的数据结构,左括号直接入栈,出现右括号则比较栈顶元素,如果相同,则出栈,继续比较,否则则说明不匹配。完成比较之后,如果栈已空,则说明括号完成了完全的匹配。

但是,使用字符串操作其实也能做到这一效果,完全不需要使用 Java 内置的栈。即栈顶元素可以看成是字符串的最后一个元素,出栈则是删除最后一个字符串。

解法

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
public class Solution {
public boolean isValid(String s) {
String p = "";

for (int i = 0; i < s.length(); ++i) {
String c = s.substring(i, i + 1);

if ("([{".contains(c)) {
p = p + c;
continue;
}

if (")]}".contains(c)) {
if (p.length() == 0) {
return false;
}

String topOfStack = p.substring(p.length() - 1, p.length());

if (c.equals(")") && !topOfStack.equals("(")) {
return false;
}

if (c.equals("]") && !topOfStack.equals("[")) {
return false;
}

if (c.equals("}") && !topOfStack.equals("{")) {
return false;
}

p = p.substring(0, p.length() - 1);
}
}

return p.length() == 0;
}
}

21 Merge Two Sorted Lists

概述

Merge Two Sorted Lists 即单向链表归并。

分析

归并已排序链表,首先需要判断两个链表是否已经到达链表终点,达到链表终点之后只需要处理另一个没有到达终点的链表。

在两个链表没有到达终点时,比较二者的首节点的值,在升序的情况下,较小的值添加到结果链表中,较小值所在的链表向前前进一个节点,之后周而复始的比较。

解法

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
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null && l2 == null) {
return null;
}

ListNode head = new ListNode(Integer.MIN_VALUE);
ListNode it = head;

while (l1 != null || l2 != null) {
int val = 0;

if (l1 == null) {
val = l2.val;
l2 = l2.next;
} else if (l2 == null) {
val = l1.val;
l1 = l1.next;
} else if (l1.val < l2.val) {
val = l1.val;
l1 = l1.next;
} else {
val = l2.val;
l2 = l2.next;
}

if (it.val == Integer.MIN_VALUE) {
it.val = val;
continue;
}

it.next = new ListNode(val);
it = it.next;
}

return head;
}
}