24. Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list’s nodes (i.e., only nodes themselves may be changed.)

先建立一个哨兵节点,next指向head。
交换时同时传入前一个节点pre和当前节点root。
当当前节点非null且下一个节点非null,则可以交换两个节点。
首先保存当前节点的下一个节点next和下一个节点的下一个节点last。

  • 1.将pre指向next。
  • 2.将next指向root。
  • 3.将root指向last。
  • 4.处理下一组节点,root作为pre,root.next作为root递归。
    最后返回哨兵节点的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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0, head);
swap(dummy, head);
return dummy.next;
}

private void swap(ListNode pre, ListNode root){
if(root == null || root.next == null){
return;
}
else if(root != null && root.next != null){

ListNode last = root.next.next;
ListNode next = root.next;
pre.next = next;
next.next = root;
root.next = last;
}
swap(root, root.next);
}
}

160. Intersection of Two Linked Lists

Given the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.

For example, the following two linked lists begin to intersect at node c1:

The test cases are generated such that there are no cycles anywhere in the entire linked structure.

Note that the linked lists must retain their original structure after the function returns.

计算两个链表的长度。将长的链表向下移动两者长度的差,对齐两个链表的长度。
同时向下移动两个链表,如果两个节点的内存地址相同,则返回节点。否则返回null。

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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int sizeA = 0, sizeB = 0;
ListNode l1 = headA, l2 = headB;

while(l1 != null){
l1 = l1.next;
sizeA++;
}
while(l2 != null){
l2 = l2.next;
sizeB++;
}
if(sizeA > sizeB){
int size = sizeA - sizeB;
while(size != 0){
headA = headA.next;
size--;
}
}
else{
int size = sizeB - sizeA;
while(size != 0){
headB = headB.next;
size--;
}
}
while(headA != null){
if(headA == headB) return headA;
headA = headA.next;
headB = headB.next;
}
return null;
}
}

遍历移动一个链表,将其加入哈希集合。
然后移动另一个链表,如果哈希集合中有重复节点,则返回该节点。

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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set = new HashSet<>();
while(headA != null){
set.add(headA);
headA = headA.next;
}
while(headB != null){
if(set.contains(headB)) return headB;
headB = headB.next;
}
return null;
}
}

79. Word Search

Given an m x n grid of characters board and a string word, return true if word exists in the grid.

The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.

回溯,遍历所有初始元素。
当寻找的字符与当前matrix里的字符相同时,将当前位置记录在visited里,并向下递归搜索四个方向,回溯visited。
当越界或者字符已经visited时返回false。
当寻找到单词的最后一位时,如果当前matrix里的字符与搜索的字符相等,则返回true。反之返回false。

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
class Solution {
char[][] bd;
String wd;
int[][] visited;
public boolean exist(char[][] board, String word) {
boolean ans = false;
visited = new int[board.length][board[0].length];
bd = board;
wd = word;
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
ans = ans || backtracking(i, j, 0);
}
}
return ans;
}

private boolean backtracking(int i, int j, int n){

if(i < 0 || j < 0 || i >= bd.length || j >= bd[0].length || n >= wd.length()) return false;
if(visited[i][j] == 1) return false;
if(n == wd.length()-1) return bd[i][j] == wd.charAt(n);
if( bd[i][j] == wd.charAt(n) ){
n++;
visited[i][j] = 1;
boolean a = backtracking(i+1, j, n);
boolean b = backtracking(i-1, j, n);
boolean c = backtracking(i, j+1, n);
boolean d = backtracking(i, j-1, n);
visited[i][j] = 0;
return a || b || c || d;
}
return false;
}
}

22. Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

回溯,记录左右括号的出现次数。
每次递归都添加左侧括号。
左侧括号的数量大于右侧括号时递归下一级才可以添加右侧括号。
当左侧括号和右侧括号达到n时,返回字符串。

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
class Solution {
int N;
List<String> ret;
StringBuffer sb;

public List<String> generateParenthesis(int n) {
ret = new ArrayList<>();
sb = new StringBuffer();
N = n;
backtracking(0, 0);
return ret;
}

private void backtracking(int left, int right){
if(left > N || right > N){
return;
}
if(left == N && right == N){
ret.add(sb.toString());
return;
}
if(left > right){
sb.append(')');
backtracking(left, right+1);
sb.delete(sb.length()-1, sb.length());
}
sb.append('(');
backtracking(left+1, right);
sb.delete(sb.length()-1, sb.length());
}
}

1584. Min Cost to Connect All Points

You are given an array points representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi].

The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val.

Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.

并查集,最小生成树(Minimum spanning tree),Kruskal算法。
Edge辅助类,保存并计算两点的id和其曼哈顿距离。
将edges根据其距离排序。

遍历所有的edge,如果edge的两点没有合并,则合并两点,并取这条边作为结果。
加和所有的结果,答案就是最小值。

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
class Solution {
public int minCostConnectPoints(int[][] points) {
List<Edge> edges = new ArrayList<Edge>();
int min = 0;
for(int i = 0; i < points.length; i++){
for(int j = i+1; j < points.length; j++){
edges.add(new Edge(points, i, j));
}
}

Collections.sort(edges, (a, b) -> a.length - b.length);
UnionFind uf = new UnionFind(points.length);

for(Edge e : edges){
if(uf.union(e.id1, e.id2)){
min += e.length;
}
}
return min;
}

class UnionFind{
private int[] parents;
private int[] size;

public UnionFind(int n){
size = new int[n];
parents = new int[n];
for(int i = 0; i < n; i++){
parents[i] = i;
size[i] = 1;
}
}

public int find(int id){
if(parents[id] == id) return id;
return find(parents[id]);
}

public boolean union(int id1, int id2){
int p1 = find(id1);
int p2 = find(id2);

if(p1 == p2) return false;

if(size[p1] < size[p2]){
parents[p1] = p2;
size[p2] += size[p1];
}
else{
parents[p2] = p1;
size[p1] += size[p2];
}
return true;
}
}

class Edge{
int id1;
int id2;
int length;
public Edge(int[][] points, int _id1, int _id2){
id1 = _id1;
id2 = _id2;
length = Math.abs(points[id1][0] - points[id2][0]) + Math.abs(points[id1][1] - points[id2][1]);
}
}
}