0%

线性数据结构

线性数据结构相关题目,队列,栈,链表,数组===

1. 用数组结构实现大小固定的队列和栈

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
public class Code_01_Array_To_Stack_Queue {
public static class ArrayStack {
private Integer[] arr;
private Integer index;

public ArrayStack(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new Integer[initSize];
index = 0;
}

public Integer peak() {
if (index == 0) {
return null;
}
return arr[index - 1];
}

public void push(int obj) {
if (index == arr.length) {
throw new ArrayIndexOutOfBoundsException("The stack is full");
}
arr[index++] = obj;
}

public Integer pop() {
if (index == 0) {
throw new ArrayIndexOutOfBoundsException("The stack is empty");
}
return arr[--index];
}
}

public static class ArrayQueue {
private Integer[] arr;
private Integer size;
private Integer start;
private Integer end;

public ArrayQueue(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("The init size is less than 0");
}
arr = new Integer[initSize];
size = 0;
start = 0;
end = 0;
}

public Integer peek() {
if (size == 0) {
return null;
}
return arr[start];
}

public void push(int obj) {
if (size == arr.length) {
throw new ArrayIndexOutOfBoundsException("The queue is full");
}
size++;
arr[end] = obj;
end = end == arr.length - 1 ? 0 : end + 1;
}

public Integer poll() {
if (size == 0) {
throw new ArrayIndexOutOfBoundsException("The queue is empty");
}
size--;
int tmp = start;
start = start == arr.length - 1 ? 0 : start + 1;
return arr[tmp];
}
}

public static void main(String[] args) {

}
}

2. 最小栈

image-20200924164855781

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
import java.util.Stack;

public class Code_02_GetMinStack {
public static class MyStack1{
private Stack<Integer> stackData;
private Stack<Integer> stackMin;

public MyStack1() {
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}
public void push(int newNum){
if(this.stackMin.isEmpty()){
this.stackMin.push(newNum);
} else if(newNum<=this.getMin()){
this.stackMin.push(newNum);
}
this.stackData.push(newNum);
}
public int pop(){
if(this.stackData.isEmpty()){
throw new RuntimeException("Your stack is empty");
}
int value = this.stackData.pop();
if(value==this.getMin()){
this.stackMin.pop();
}
return value;
}
public int getMin(){
if (this.stackMin.isEmpty()) {
throw new RuntimeException("Your stack is empty");
}
return this.stackMin.peek();
}
}

public static class MyStack2 {
private Stack<Integer> stackData;
private Stack<Integer> stackMin;

public MyStack2() {
this.stackData = new Stack<Integer>();
this.stackMin = new Stack<Integer>();
}

public void push(int newNum) {
if (this.stackMin.isEmpty()) {
this.stackMin.push(newNum);
} else if (newNum < this.getMin()) {
this.stackMin.push(newNum);
} else {
int newMin = this.getMin();
this.stackMin.push(newMin);
}
this.stackData.push(newNum);
}

public int pop() {
if (this.stackData.isEmpty()) {
throw new RuntimeException("Your stack is empty");
}
this.stackMin.pop();
return this.stackData.pop();
}

public int getMin() {
if (this.stackMin.isEmpty()) {
throw new RuntimeException("Your stack is empty");
}
return this.stackMin.peek();
}
}
}

3. 仅用队列实现栈结构,仅用栈实现队列结构

用队列如何实现图的深度优先遍历?—- 队列实现栈

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
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class Code_03_StackAndQueueConvert {

public static class TwoStacksQueue {
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;

public TwoStacksQueue() {
stackPush = new Stack<Integer>();
stackPop = new Stack<Integer>();
}

public void push(int pushInt) {
stackPush.push(pushInt);
}

public int poll() {
if (stackPop.empty() && stackPush.empty()) {
throw new RuntimeException("Queue is empty!");
} else if (stackPop.empty()) {
while (!stackPush.empty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}

public int peek() {
if (stackPop.empty() && stackPush.empty()) {
throw new RuntimeException("Queue is empty!");
} else if (stackPop.empty()) {
while (!stackPop.empty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.peek();
}
}

public static class TwoQueuesStack {
private Queue<Integer> data;
private Queue<Integer> help;

public TwoQueuesStack() {
data = new LinkedList<Integer>();
help = new LinkedList<Integer>();
}

public void push(int pushInt) {
data.add(pushInt);
}

public int peek() {
if (data.isEmpty()) {
throw new RuntimeException("Stack is empty!");
}
while (data.size() != 1) {
help.add(data.poll());
}
int res = data.poll();
help.add(res);
swap();
return res;
}

public int pop() {
if (data.isEmpty()) {
throw new RuntimeException("Stack is empty!");
}
while (data.size() > 1) {
help.add(data.poll());
}
int res = data.poll();
swap();
return res;
}

private void swap() {
Queue<Integer> tmp = help;
help = data;
data = tmp;
}
}
}

4. 猫狗队列

image-20200924203447304

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
import java.util.LinkedList;
import java.util.Queue;

public class Code_04_DogCatQueue {
public static class Pet {
private String type;

public Pet(String type) {
this.type = type;
}

public String getPetType() {
return this.type;
}
}

public static class Dog extends Pet {
public Dog() {
super("dog");
}
}

public static class Cat extends Pet {
public Cat() {
super("cat");
}
}

public static class PetEnter {
private Pet pet;
private long count;

public PetEnter(Pet pet, long count) {
this.pet = pet;
this.count = count;
}

public Pet getPet() {
return this.pet;
}

public long getCount() {
return this.count;
}

public String getEnterPetType() {
return this.pet.getPetType();
}
}

public static class DogCatQueue {
private Queue<PetEnter> dogQ;
private Queue<PetEnter> catQ;
private long count;

public DogCatQueue() {
this.dogQ = new LinkedList<PetEnter>();
this.catQ = new LinkedList<PetEnter>();
this.count = 0;
}

public void add(Pet pet) {
if (pet.getPetType().equals("dog")) {
this.dogQ.add(new PetEnter(pet, this.count++));
} else if (pet.getPetType().equals("cat")) {
this.catQ.add(new PetEnter(pet, count++));
} else {
throw new RuntimeException("error,not dog or cat");
}
}

public Pet pollAll() {
if (!this.dogQ.isEmpty() && !this.catQ.isEmpty()) {
if (this.dogQ.peek().getCount() < this.catQ.peek().getCount()) {
return this.dogQ.poll().getPet();
} else {
return this.catQ.poll().getPet();
}
} else if (!this.dogQ.isEmpty()) {
return this.dogQ.poll().getPet();
} else if (!this.catQ.isEmpty()) {
return this.catQ.poll().getPet();
} else {
throw new RuntimeException("error,queue is empty!");
}
}

public Dog pollDog() {
if (!this.dogQ.isEmpty()) {
return (Dog) this.dogQ.poll().getPet();
} else {
throw new RuntimeException("Dog queue is empty!");
}
}

public Cat pollCat() {
if (!this.catQ.isEmpty()) {
return (Cat) this.catQ.poll().getPet();
} else {
throw new RuntimeException("Cat queue is empty!");
}
}

public boolean isEmpty() {
return this.dogQ.isEmpty() && this.catQ.isEmpty();
}

public boolean isDogQueueEmpty() {
return this.dogQ.isEmpty();
}

public boolean isCatQueueEmpty() {
return this.catQ.isEmpty();
}
}
}

5. 转圈打印矩阵

image-20200924211903946

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
public class Code_06_PrintMatrixSpiralOrder {

public static void spiralOrderPrint(int[][] matrix) {
int tR = 0;
int tC = 0;
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
while (tR<=dR && tC<=dC){
printEdge(matrix,tR++,tC++,dR--,dC--);
}
}

public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
if (tR == dR) {
for (int i = tC; i <= dC; i++) {
System.out.print(m[tR][i] + " ");
}
} else if (tC == dC) {
for (int i = tR; i <= dR; i++) {
System.out.print(m[i][tC] + " ");
}
} else {
int curC = tC;
int curR = tR;
while (curC != dC) {
System.out.print(m[tR][curC] + " ");
curC++;
}
while (curR != dR) {
System.out.print(m[curR][dC] + " ");
curR++;
}
while (curC != tC) {
System.out.print(m[dR][curC] + " ");
curC--;
}
while (curR != tR) {
System.out.print(m[curR][tC] + " ");
curR--;
}
}
}
}

6. 旋转正方形矩阵

image-20200924220049013

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Code_05_RotateMatrix {
public static void rotate(int[][] matrix) {
int tR = 0;
int tC = 0;
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
while (tR < dR) {
rotateEdge(matrix, tR++, tC++, dR--, dC--);
}
}

public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) {
int times = dC - tC;
int tmp = 0;
for (int i = 0; i < times; i++) {
tmp = m[tR][tC + i];
m[tR][tC + i] = m[dR - i][tC];
m[dR - i][tC] = m[dR][dC - i];
m[dR][dC - i] = m[tR + i][dC];
m[tR + i][dC] = tmp;
}
}
}

7. 反转单向和双向链表

image-20200925104239789

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
public class Code_07_ReverseList {
public static class Node {
public int value;
public Node next;

public Node(int data) {
this.value = data;
}
}

public static Node reverseList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}

public static class DoubleNode {
public int value;
public DoubleNode last;
public DoubleNode next;

public DoubleNode(int data) {
this.value = data;
}
}

public static DoubleNode reverseList(DoubleNode head) {
DoubleNode pre = null;
DoubleNode next = null;
while (head!=null){
next = head.next;
head.next =pre;
head.last = next;
pre = head;
head = next;
}
return pre;
}
}

8. “之”字形打印矩阵

image-20200925111934416

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
public class Code_08_ZigZagPrintMatrix {
public static void printMatrixZigZag(int[][] matrix) {
int tR = 0;
int tC = 0;
int dR = 0;
int dC = 0;
int endR = matrix.length - 1;
int endC = matrix[0].length - 1;
boolean fromUp = false;
while (tR != endR + 1) {
printLevel(matrix, tR, tC, dR, dC, fromUp);
tR = tC == endC ? tR + 1 : tR;
tC = tC == endC ? tC : tC + 1;
dC = dR == endR ? dC + 1 : dC;
dR = dR == endR ? dR : dR + 1;
fromUp = !fromUp;
}
System.out.println();
}

public static void printLevel(int[][] matrix, int tR, int tC, int dR, int dC, boolean fromUp) {
if (fromUp) {
while (tR != dR + 1) {
System.out.print(matrix[tR++][tC--] + " ");
}
} else {
while (dR != tR - 1) {
System.out.print(matrix[dR--][dC++] + " ");
}
}
}

public static void main(String[] args) {
int[][] matrix = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
printMatrixZigZag(matrix);
}
}

9. 在行列都排好序的矩阵中找数

image-20200928203038743

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
public class Code_09_FindNumInSortedMatrix {
public static boolean isContains(int[][] matrix, int K) {
int row = 0;
int col = matrix[0].length - 1;
while (row < matrix.length && col > -1) {
if(matrix[row][col]==K){
return true;
}else if (matrix[row][col]>K){
col--;
}else {
row++;
}
}
return false;
}

public static void main(String[] args) {
int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
{ 10, 12, 13, 15, 16, 17, 18 },// 1
{ 23, 24, 25, 26, 27, 28, 29 },// 2
{ 44, 45, 46, 47, 48, 49, 50 },// 3
{ 65, 66, 67, 68, 69, 70, 71 },// 4
{ 96, 97, 98, 99, 100, 111, 122 },// 5
{ 166, 176, 186, 187, 190, 195, 200 },// 6
{ 233, 243, 321, 341, 356, 370, 380 } // 7
};
int K = 233;
System.out.println(isContains(matrix, K));
}
}

10.打印两个有序链表的公共部分

image-20200928203303735

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
public class Code_10_PrintCommonPart {
public static class Node {
public int value;
public Node next;

public Node(int data) {
this.value = data;
}
}

public static void printCommonPart(Node head1, Node head2) {
System.out.print("Common Part: ");
while (head1 != null && head2 != null) {
if (head1.value < head2.value) {
head1 = head1.next;
} else if (head1.value > head2.value) {
head2 = head2.next;
} else {
System.out.print(head1.value + " ");
head1 = head1.next;
head2 = head2.next;
}
}
System.out.println();
}
}

11.判断一个链表是否为回文结构

image-20201021143912404

链表类题目的最优一般在额外空间复杂度O(1)下考虑,笔试中尽快使用额外空间解决,面试给出最优解。

  • 对整个链表压栈,pop为逆序,与原链表比较 O(N)额外空间
  • 快慢指针,快指针一次走两步,慢指针一次走一步,得到中点后,后半段压栈,pop与前半段比较 一半额外空间
  • 最优解:快慢指针,得到中点后,将后半段逆序,从两端逐一比较,不管返回true or 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
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
package basic_class_03;
import java.util.Stack;

public class Code_11_IsPalindromeList {
public static class Node {
public int value;
public Node next;

public Node(int data) {
this.value = data;
}
}

// need n extra space
public static boolean isPalindrome1(Node head) {
Stack<Node> stack = new Stack<Node>();
Node cur = head;
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
while (head != null) {
if (head.value != stack.pop().value) {
return false;
}
head = head.next;
}
return true;
}

// need n/2 extra space
public static boolean isPalindrome2(Node head) {
if (head == null || head.next == null) {
return true;
}
Node right = head.next;
Node cur = head;
while (cur.next != null && cur.next.next != null) {
right = right.next;
cur = cur.next.next;
}
Stack<Node> stack = new Stack<Node>();
while (right != null) {
stack.push(right);
right = right.next;
}
while (!stack.isEmpty()) {
if (head.value != stack.pop().value) {
return false;
}
head = head.next;
}
return true;
}

// need O(1) extra space
public static boolean isPalindrome3(Node head) {
if (head == null || head.next == null) {
return true;
}
Node n1 = head;
Node n2 = head;
while (n2.next != null && n2.next.next != null) { // find mid node
n1 = n1.next; //n1->mid
n2 = n2.next.next; //n2->end
}
n2 = n1.next; //n2->right part first node
n1.next = null; //mid.next->null
Node n3 = null;
while (n2 != null) { //right part convert
n3 = n2.next; //n3->save next node
n2.next = n1; //next of right node convert
n1 = n2; //n1 move
n2 = n3; //n2 move
}
n3 = n1; // n3-> save last node
n2 = head; // n2-> left first node
boolean res = true;
while (n1 != null && n2 != null) { // check palindrome
if (n1.value != n2.value) {
res = false;
break;
}
n1 = n1.next;
n2 = n2.next;
}
n1 = n3.next;
n3.next = null;
while (n1 != null) {
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
}

12.将单向链表按某值划分成左边小,中间相等,右边大的形式

image-20201021153604446

  • 使用辅助数组,荷兰国旗问题,排序后再串为链表
  • less ,equal,more 三个变量,初始为null,遍历一遍链表,找到第一个小于num,等于num,大于num的节点,第二编遍历链表,除第一次遍历的三个节点外,依次按类别挂在less,equal,more后 ,最后三部分重连,每部分一个end变量,共6个变量。
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
public class Code_12_SmallerEqualBigger {
public static class Node {
public int value;
public Node next;

public Node(int data) {
this.value = data;
}
}

public static Node listPartition1(Node head, int pivot) {
if (head == null) {
return head;
}
Node cur = head;
int i = 0;
while (cur != null) {
i++;
cur = cur.next;
}
Node[] nodeArr = new Node[i];
i = 0;
cur = head;
for (i = 0; i != nodeArr.length; i++) {
nodeArr[i] = cur;
cur = cur.next;
}
arrPartition(nodeArr, pivot);
for (i = 1; i != nodeArr.length; i++) {
nodeArr[i - 1].next = nodeArr[i];
}
nodeArr[i - 1].next = null;
return nodeArr[0];
}

public static void arrPartition(Node[] nodeArr, int pivot) {
int small = -1;
int big = nodeArr.length;
int index = 0;
while (index != big) {
if (nodeArr[index].value < pivot) {
swap(nodeArr, ++small, index++);
} else if (nodeArr[index].value == pivot) {
index++;
} else {
swap(nodeArr, --big, index);
}
}
}

public static void swap(Node[] nodeArr, int a, int b) {
Node tmp = nodeArr[a];
nodeArr[a] = nodeArr[b];
nodeArr[b] = tmp;
}

public static Node listPartition2(Node head, int pivot) {
Node sH = null;//small head
Node sT = null;//small tail
Node eH = null;//equal head
Node eT = null;//equal tail
Node bH = null;//big head
Node bT = null;//big tail
Node next = null; // save next node
//every node distributed to three lists
while (head != null) {
next = head.next;
head.next = null;
if (head.value < pivot) {
if (sH == null) {
sH = head;
sT = head;
} else {
sT.next = head;
sT = head;
}
} else if (head.value == pivot) {
if (eH == null) {
eH = head;
eT = head;
} else {
eT.next = head;
eT = head;
}
} else {
if (bH == null) {
bH = head;
bT = head;
} else {
bT.next = head;
bT = head;
}
}
head = next;
}
//small and equal reconnect
if (sT != null) {
sT.next = eH;
eT = eT == null ? sT : eT;
}
// all reconnect
if (eT != null) {
eT.next = bH;
}
return sH != null ? sH : eH != null ? eH : bH;
}
}

13. 复制含有随机指针节点的链表

image-20201021163416942

  • HashMap ,两次遍历,一次拷贝节点,一次拷贝关系
  • 不用哈希表,O(1)空间复杂度:拷贝节点放在链表中源节点的下一个
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 basic_class_03;

import java.util.HashMap;

public class Code_13_CopyListWithRandom {
public static class Node {
public int value;
public Node next;
public Node rand;

public Node(int data) {
this.value = data;
}
}

public static Node copyListWithRand1(Node head) {
HashMap<Node, Node> map = new HashMap<Node, Node>();
Node cur = head;
while (cur != null) {
map.put(cur, new Node(cur.value));
cur = cur.next;
}
cur = head;
while (cur != null) {
map.get(cur).next = map.get(cur.next);
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;
}
return map.get(head);
}

public static Node copyListWithRand2(Node head) {
if (head == null) {
return null;
}
Node cur = head;
Node next = null;
//copy node and link to every node
while (cur != null) {
next = cur.next;
cur.next = new Node(cur.value);
cur.next.next = next;
cur = next;
}
cur = head;
Node curCopy = null;
//set copy node rand
while (cur != null) {
next = cur.next.next;
curCopy = cur.next;
curCopy.rand = cur.rand != null ? cur.rand.next : null;
cur = next;
}
Node res = head.next;
cur = head;
// split
while (cur != null) {
next = cur.next.next;
curCopy = cur.next;
cur.next = next;
curCopy.next = next != null ? next.next : null;
cur = next;
}
return res;
}
}

14. 两个单链表相交的一系列问题

image-20201021163448455

  • 判断链表是否有环:1,HashSet;2,快慢指针:快指针一次走两步,慢指针一次走一步,如果快指针到null,无环;快指针与慢指针相遇,有环,此时,快指针从head开始,一次一步,与慢指针再次相遇的时候就是第一个入环节点。

  • 两个链表都无环: 1, HashSet; 2,遍历得到两个链表的长度和最后一个节点,最后节点内存地址相等,有公共部分,否则无;长度长的链表先走长度差值步,然后两个链表一起走,得到第一个相交的节点。

  • 一个链表有环,一个链表无环,不可能相交。

  • 两个链表都有环:只有三种拓扑结构。1,各自成环,不相交;2,先相交再共享一个环(入环节点相同,loop1=loop2),求解方法等同于无环链表相交;3,最右侧

    image-20201021174105883

    loop1!=loop2: loop1继续走,走回自己没有碰到loop2,为第一种结构,遇到loop2,为第三种结构(返回loop1和loop2都对)。

    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
    public class Code_14_FindFirstIntersectNode {
    public static class Node {
    public int value;
    public Node next;

    public Node(int data) {
    this.value = data;
    }
    }

    public static Node getIntersectNode(Node head1, Node head2) {
    if (head1 == null || head2 == null) {
    return null;
    }
    Node loop1 = getLoopNode(head1);
    Node loop2 = getLoopNode(head2);
    if (loop1 == null && loop2 == null) {
    return noLoop(head1, head2);
    }
    if (loop1 != null && loop2 != null) {
    return bothLoop(head1, loop1, head2, loop2);
    }
    return null;
    }

    public static Node getLoopNode(Node head) {
    if (head == null || head.next == null || head.next.next == null) {
    return null;
    }
    Node n1 = head.next;
    Node n2 = head.next.next;
    while (n1 != n2) {
    if (n2.next == null || n2.next.next == null) {
    return null;
    }
    n2 = n2.next.next;
    n1 = n1.next;
    }
    n2 = head;
    while (n1 != n2) {
    n1 = n1.next;
    n2 = n2.next;
    }
    return n1;
    }

    public static Node noLoop(Node head1, Node head2) {
    if (head1 == null || head2 == null) {
    return null;
    }
    Node cur1 = head1;
    Node cur2 = head2;
    int n = 0;
    while (cur1.next != null) {
    n++;
    cur1 = cur1.next;
    }
    while (cur2.next != null) {
    n--;
    cur2 = cur2.next;
    }
    if (cur1 != cur2) {
    return null;
    }
    cur1 = n > 0 ? head1 : head2;
    cur2 = cur1 == head1 ? head2 : head1;
    n = Math.abs(n);
    while (n != 0) {
    n--;
    cur1 = cur1.next;
    }
    while (cur1 != cur2) {
    cur1 = cur1.next;
    cur2 = cur2.next;
    }
    return cur1;
    }

    public static Node bothLoop(Node head1, Node loop1, Node head2, Node loop2) {
    Node cur1 = null;
    Node cur2 = null;
    if (loop1 == loop2) {
    cur1 = head1;
    cur2 = head2;
    int n = 0;
    while (cur1 != loop1) {
    n++;
    cur1 = cur1.next;
    }
    while (cur2 != loop2) {
    n--;
    cur2 = cur2.next;
    }
    cur1 = n > 0 ? head1 : head2;
    cur2 = cur1 == head1 ? head2 : head1;
    n = Math.abs(n);
    while (n != 0) {
    n--;
    cur1 = cur1.next;
    }
    while (cur1 != cur2) {
    cur1 = cur1.next;
    cur2 = cur2.next;
    }
    return cur1;
    } else {
    cur1 = loop1.next;
    while (cur1 != loop1) {
    if (cur1 == loop2) {
    return loop1;
    }
    cur1 = cur1.next;
    }
    return null;
    }
    }
    }

15. 二分的小扩展

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
public class Code_15_FindOneLessValueIndex {
public static int getLessIndex(int[] arr) {
if (arr == null || arr.length == 0) {
return -1;
}
if (arr.length == 1 || arr[0] < arr[1]) {
return 0;
}
if (arr[arr.length - 1] < arr[arr.length - 2]) {
return arr.length - 1;
}
int left = 1;
int right = arr.length - 2;
int mid = 0;
while (left < right) {
mid = (left + right) / 2;
if (arr[mid] > arr[mid - 1]) {
right = mid - 1;
} else if (arr[mid] > arr[mid + 1]) {
left = mid + 1;
} else {
return mid;
}
}
return left;
}
}