
// 单链表节点的结构
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;
    }