// 单链表节点的结构
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
在java中 HashSet就是一个只使用HashMap的key的一个集合。
有序表的固定操作:
节点结构:
public class TreeNode {
public int num;
public TreeNode next;
public TreeNode last;
public TreeNode(int num) {
this.num = num;
}
public TreeNode() {}
}
public class Node {
public int num;
public Node next;
public Node(int num, Node next) {
this.num = num;
this.next = next;
}
}
两种方式反转链表结构:
/**
* 反转单向链表
* while循环
*/
public static Node reversal1(Node head) {
Node last = head.next;
head.next = null;
while (last != null) {
Node temp = last.next;
last.next = head;
head = last;
last = temp;
}
return head;
}
/**
* 反转单链表
* 递归
* @param head
* @return
*/
public static Node reversal2(Node head) {
if(head.next == null) {
return head;
}
Node last = reversal2(head.next);
head.next.next = head;
head.next = null;
return last;
}
/**
* 反转双向链表
* 循环
* @param head
* @return
*/
public static TreeNode reversal3(TreeNode head) {
TreeNode next = head.next;
head.next = null;
while (next != null) {
head.last = next;
TreeNode temp = next.next;
next.next = head;
head = next;
next = temp;
}
return head;
}
/**
* 反转双向链表
* 递归
* @param head
* @return
*/
public static TreeNode reversal4(TreeNode head) {
if (head.next == null) {
return head;
}
TreeNode node = reversal4(head.next);
head.next.last = head.next.next;
head.next.next = head;
head.next = null;
return node;
}
public static void portion(Node n1, Node n2) {
while(n1 != null && n2 != null) {
if (n1.num == n2.num) {
System.out.print(n1.num);
n1 = n1.next;
n2 = n2.next;
}else if (n1.num < n2.num) {
n1 = n1.next;
}else if (n1.num > n2.num) {
n2 = n2.next;
}
}
}
/**
* 不使用额外的空间,适用于面试
* @param head
* @return
*/
public static boolean plalindrome2(Node head) {
//首先通过快慢指针找到中间的节点,如果是偶数:中间左边,奇数:中间节点
Node slowNode = head;
Node quickNode = head;
while(quickNode.next!= null && quickNode.next.next != null) {
slowNode = slowNode.next;
quickNode = quickNode.next.next;
}
//此时慢指针,就到了中间位置,那么在此后面的的节点 指针反转
quickNode = slowNode.next;
slowNode.next = null;
while (quickNode != null) {
Node temp = quickNode.next;
quickNode.next = slowNode;
slowNode = quickNode;
quickNode = temp;
}
while (head.next != null && slowNode.next != null) {
if (head.num != slowNode.num) {
return false;
}
head = head.next;
slowNode = slowNode.next;
}
return true;
}
/**
* 使用额外的数据结构,空间复杂度高,适用于笔试
* @param head
* @return
*/
public static boolean plalindrome1(Node head) {
Stack<Node> stack = new Stack();
Node node = head;
while (node != null) {
stack.add(node);
node = node.next;
}
while (head != null) {
if (head.num != stack.pop().num) {
return false;
}
head = head.next;
}
return true;
}
【题目】给定一个单链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。
/**
* 使用有限的变量解答题目
* @param node
* @param num
* @return
*/
private static Node pivot1(Node node, int num) {
Node ssNode = null;
Node seNode = null;
Node msNode = null;
Node meNode = null;
Node bsNode = null;
Node beNode = null;
while (node != null) {
if (node.num < num) {
if (ssNode != null) {
seNode.next = node;
seNode = node;
}else {
ssNode = node;
seNode = node;
}
}else if (node.num > num) {
if (bsNode != null) {
beNode.next = node;
beNode = node;
}else {
bsNode =node;
beNode = node;
}
}else if (node.num == num){
if (msNode != null) {
meNode.next = node;
meNode = node;
}else {
msNode = node;
meNode = node;
}
}
node = node.next;
}
if (ssNode == null) {
if (meNode == null) {
ssNode = bsNode;
}else {
meNode.next= bsNode;
ssNode = msNode;
}
}else {
if (meNode == null) {
seNode.next = bsNode;
}else {
seNode.next = msNode;
meNode.next = bsNode;
}
}
return ssNode;
}
/**
* 采用数组 的结构 然后利用快速排序的思路,进行处理
* @param node
* @param num
*/
private static void pivot(Node node, int num) {
Node[] nodes = new Node[6];
int i = 0;
while (node != null) {
nodes[i++] = node;
node = node.next;
}
System.out.println(Arrays.toString(nodes));
int start = 0, end = nodes.length-1;
for (int j = 0; j <= end; j++) {
if (nodes[j].num < num) {
Node temp = nodes[j];
nodes[j] = nodes[start];
nodes[start] = temp;
start++;
}else if (nodes[j].num > num) {
Node temp = nodes[j];
nodes[j] = nodes[end];
nodes[end] = temp;
j--;
end --;
}
}
System.out.println(Arrays.toString(nodes));
}
【题目】一种特殊的单链表节点类描述如下
class Node {
int value;
Node next;
Node rand;
Node(int val) {
value = val;
}
}
rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节 点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。 【要求】时间复杂度O(N),额外空间复杂度O(1)
/**
* 使用 Map数据结构
* @param head
* @return
*/
public static ListNode copy(ListNode head) {
Map<ListNode, ListNode> map = new HashMap<>();
ListNode node = head;
while (node != null) {
map.put(node, new ListNode(node.value));
node = node.next;
}
ListNode hListNode = head;
while (head != null) {
map.get(head).next = map.get(head.next);
map.get(head).rand = map.get(head.rand);
head = head.next;
}
return map.get(hListNode);
}
/**
* 不使用额外空间
* @param head
* @return
*/
public static ListNode copy1(ListNode head) {
ListNode node = head;
ListNode temp;
while (node != null) {
temp = node.next;
node.next = new ListNode(node.value);
node.next.next = temp;
node = temp;
}
node = head;
while (node != null) {
temp = node.next;
if (node.rand == null) {
temp.rand = null;
}else {
temp.rand = node.rand.next;
}
node = node.next.next;
}
return head.next;
}
【题目】给定两个可能有环也可能无环的单链表,头节点head1和head2。请实 现一个函数,如果两个链表相交,请返回相交的 第一个节点。如果不相交,返 回null 【要求】如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度 请达到O(1)。
//没做
public ListNode reverse(ListNode head) {
if (head.next == null) {
return head;
}
ListNode lastListNode = reverse(head.next);
head.next.next = head;
head.next = null;
return lastListNode;
}
ListNode successor = null; // 后驱节点
// 反转以 head 为起点的 n 个节点,返回新的头结点
public ListNode reverseN(ListNode head, int n) {
if (n == 1) {
// 记录第 n + 1 个节点
successor = head.next;
return head;
}
// 以 head.next 为起点,需要反转前 n - 1 个节点
ListNode last = reverseN(head.next, n - 1);
head.next.next = head;
// 让反转之后的 head 节点和后面的节点连起来
head.next = successor;
return last;
}
ListNode reverseBetween(ListNode head, int m, int n) {
// base case
if (m == 1) {
return reverseN(head, n);
}
// 前进到反转的起点触发 base case
head.next = reverseBetween(head.next, m - 1, n - 1);
return head;
}
**递归的思想相对迭代思想,稍微有点难以理解,处理的技巧是:**不要跳进递归,而是利用明确的定义来实现算法逻辑。
/**
* 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 success1 = null;
public ListNode reverseBetween(ListNode head, int left, int right) {
if (left == 1) {
return reverseBetween(head, right);
}
head.next = reverseBetween(head.next, --left, --right);
return head;
}
public ListNode reverseBetween(ListNode head, int n) {
if (n == 1) {
success1 = head.next;
return head;
}
ListNode laListNode = reverseBetween(head.next, --n);
head.next.next = head;
head.next = success1;
return laListNode;
}
}
我的代码:
/**
* 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 reverseKGroup(ListNode head, int k) {
ListNode[] arr = reverse(head, k);
ListNode preListNode = arr[2];
ListNode preListNode1 = arr[0];
while (arr[1] != null) {
if (!judge(arr[1], k)) {
break;
}
arr = reverse(arr[1], k);
preListNode.next = arr[0];
preListNode = arr[2];
}
return preListNode1;
}
public boolean judge(ListNode head, int k) {
ListNode node = head;
while (node != null) {
node = node.next;
k--;
if (k == 0) {
return true;
}
}
return false;
}
public ListNode[] reverse(ListNode head, int k) {
ListNode[] arr = new ListNode[3];
ListNode preNode = head;
ListNode currentNode = head.next;
ListNode tempListNode = null;
while (currentNode != null&&k>1) {
tempListNode = currentNode.next;
currentNode.next = preNode;
preNode = currentNode;
currentNode = tempListNode;
if (k == 2) {
break;
}
--k;
}
head.next = currentNode;
arr[0] = preNode;
arr[1] = currentNode;
arr[2] = head;
return arr;
}
}
拉布拉多
/**
* 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 reverseKGroup(ListNode head, int k) {
if (head == null) {
return null;
}
ListNode a,b;
a = head;
b = head;
for (int i = 0; i < k; i++) {
if (b == null) {
return head;
}
b = b.next;
}
// 反转前 k 个元素
ListNode newHead = reverse(a, b);
// 递归反转后续链表并连接起来
a.next = reverseKGroup(b, k);
return newHead;
}
public ListNode reverse(ListNode a, ListNode b) {
ListNode pre,cur,temp;
pre = a;
cur = a.next;
while (cur != b) {
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
空间复杂度为O(1)的
/**
* 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 boolean isPalindrome(ListNode head) {
ListNode a = head;
ListNode b = head;
while (b.next != null && b.next.next != null) {
b = b.next.next;
a = a.next;
}
ListNode c;
c = a.next;
a.next = null;
while (c != null) {
b = c.next;
c.next = a;
a = c;
c = b;
}
c = a;
b = head;
while (b != null && a != null) {
if (b.val != a.val) {
return false;
}
b = b.next;
a = a.next;
}
//复原
return true;
}
}
使用栈
/**
* 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 boolean isPalindrome(ListNode head) {
Stack<Integer> stack = new Stack<>();
ListNode node = head;
while (node != null) {
stack.add(node.val);
node = node.next;
}
while (head != null) {
if (stack.pop() != head.val) {
return false;
}
head = head.next;
}
return true;
}
}
使用递归
/**
* 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 {
ListNode left;
public boolean isPalindrome(ListNode head) {
left = head;
return traverse(head);
}
public boolean traverse(ListNode head) {
// 前序遍历代码
if (head == null) {
return true;
}
// 后序遍历代码
boolean res = traverse(head.next);
boolean b = res && head.val == left.val;
left = left.next;
return b;
}
}
//双指针
public int kthToLast(ListNode head, int k) {
ListNode n1 = head;
ListNode n2 = head;
while (k != 0) {
n1 = n1.next;
k--;
}
while (n1 != null) {
n1 = n1.next;
n2 = n2.next;
}
return n2.val;
}