/*
定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。
输入:1->2->3->4->5->NULL
输出:5->4->3->2->1->NULL
*/
// 迭代法
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
// 递归法
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode p = reverseList(head.next);
head.next.next = head;
head.next = null;
return p;
}
}
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode a = dummy;
for(int i = 0; i < left-1; i++){
a = a.next;
}
ListNode b = a.next, c = b.next;
for(int i = 0; i < right-left; i++){
ListNode d = c.next;
c.next = b;
b = c;
c = d;
}
a.next.next = c;
a.next = b;
return dummy.next;
}
}
/*
在未排序的数组中找到第 k 个最大的元素。
*/
class Solution {
public int findKthLargest(int[] nums, int k) {
return quickSort(nums, k-1, 0, nums.length - 1);
}
public int quickSort(int[] nums, int k, int l, int r) {
if(l >= r){
return nums[k];
}
int i = l-1, j = r+1, x = nums[l+r>>1];
while(i < j){
do i++; while(nums[i] > x);
do j--; while(nums[j] < x);
if(i < j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
if(k <= j){
return quickSort(nums,k,l,j);
} else {
return quickSort(nums,k,j+1,r);
}
}
}
/*
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
*/
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<>();
int res = 0;
for (int i = 0, j = 0; i < s.length(); i++) {
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
while (j < i && map.get(s.charAt(i)) > 1) {
map.put(s.charAt(j), map.get(s.charAt(j)) - 1);
j++;
}
res = Math.max(res, i - j + 1);
}
return res;
}
}
/*
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
*/
/*
思路:设置dummy头节点,先翻转k个节点内部,再改变外部连接。
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
for (ListNode p = dummy; ; ) {
ListNode q = p;
for (int i = 0; i < k && q != null; i++) {
q = q.next;
}
if (q == null) {
break;
}
ListNode a = p.next, b = a.next;
for (int i = 0; i < k - 1; i++) {
ListNode c = b.next;
b.next = a;
a = b;
b = c;
}
ListNode c = p.next;
p.next = a;
c.next = b;
p = c;
}
return dummy.next;
}
}
/*
运用你所掌握的数据结构,设计和实现一个LRU(最近最少使用)缓存机制。
实现LRUCache类:
LRUCache(int capacity) 以正整数作为容量capacity初始化LRU缓存
int get(int key) 如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组[关键字-值]。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
*/
/*
思路:哈希+双链表
*/
class LRUCache {
private HashMap<Integer, Node> map = new HashMap<>();
private Node head;
private Node tail;
private int n;
private class Node {
Node pre;
Node next;
int key, value;
public Node(int key, int value) {
this.key = key;
this.value = value;
this.pre = null;
this.next = null;
}
}
public LRUCache(int capacity) {
n = capacity;
head = new Node(-1, -1);
tail = new Node(-1, -1);
head.next = tail;
tail.pre = head;
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node node = map.get(key);
remove(node);
insert(node);
return node.value;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
Node node = map.get(key);
node.value = value;
remove(node);
insert(node);
} else {
if (map.size() == n) {
Node node = tail.pre;
remove(node);
map.remove(node.key);
}
Node node = new Node(key, value);
map.put(key, node);
insert(node);
}
}
public void remove(Node node) {
node.pre.next = node.next;
node.next.pre = node.pre;
}
public void insert(Node node) {
node.next = head.next;
node.pre = head;
head.next.pre = node;
head.next = node;
}
}
/*
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。答案中不可以包含重复的三元组。
*/
/*
思路:双指针
i < j < k 寻找满足nums[i] + nums[j] + nums[k] >= 0的最小k
*/
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
for (int j = i + 1, k = nums.length-1; j < k; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
while (j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= 0) {
k--;
}
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
res.add(list);
}
}
}
return res;
}
}
/*
给定一个数组prices,它的第i个元素prices[i]表示一支给定股票第i天的价格。
你只能选择某一天买入这只股票,并选择在未来的某一个不同的日子卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回0。
*/
/*
思路:维护1~i-1最小值,第i天卖出取最大值
*/
class Solution {
public int maxProfit(int[] prices) {
int res = 0;
for (int i = 0, minPrice = Integer.MAX_VALUE; i < prices.length; i++) {
res = Math.max(res, prices[i] - minPrice);
minPrice = Math.min(minPrice, prices[i]);
}
return res;
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
return new int[]{map.get(target - nums[i]), i};
}
map.put(nums[i], i);
}
return null;
}
}
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
}
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.add(root);
}
int cnt = 1;
while (!queue.isEmpty()) {
int n = queue.size();
List<Integer> list = new ArrayList<>();
while (n-- != 0) {
TreeNode node = queue.remove();
list.add(node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
if ((cnt++) % 2 == 0) {
Collections.reverse(list);
}
res.add(list);
}
return res;
}
}
// 递归写法
class Solution {
private List<Integer> res = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
dfs(root);
return res;
}
public void dfs(TreeNode root) {
if (root == null) {
return;
}
dfs(root.left);
res.add(root.val);
dfs(root.right);
}
}
//迭代写法
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.empty()) {
while (root != null) {
stack.add(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}
}
// 递归
class Solution {
private List<Integer> res = new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
dfs(root);
return res;
}
public void dfs(TreeNode root){
if(root == null){
return;
}
res.add(root.val);
dfs(root.left);
dfs(root.right);
}
}
// 迭代
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while(root != null || !stack.isEmpty()){
while(root != null){
res.add(root.val);
stack.push(root);
root = root.left;
}
TreeNode node = stack.pop();
root = node.right;
}
return res;
}
}
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while(root != null || !stack.isEmpty()){
while(root != null){
res.add(root.val);
stack.push(root);
root = root.right;
}
TreeNode node = stack.pop();
root = node.left;
}
Collections.reverse(res);
return res;
}
}
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1), tail = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
tail = tail.next = l1;
l1 = l1.next;
} else {
tail = tail.next = l2;
l2 = l2.next;
}
}
if (l1 != null) {
tail.next = l1;
}
if (l2 != null) {
tail.next = l2;
}
return dummy.next;
}
}
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> priorityQueue = new PriorityQueue<>((a,b)->a.val-b.val);
ListNode dummy = new ListNode(-1), tail = dummy;
for (int i = 0; i < lists.length; i++) {
if(lists[i] != null){
priorityQueue.add(lists[i]);
}
}
while (!priorityQueue.isEmpty()) {
ListNode node = priorityQueue.remove();
tail = tail.next = node;
if (node.next != null) {
priorityQueue.add(node.next);
}
}
return dummy.next;
}
}
class Solution {
// 是否是最近公共祖先,第一次包含
private TreeNode ans = null;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
dfs(root, p, q);
return ans;
}
//函数返回子树中是否包含p或q,00代表不包含,01代表包含p,10代表包含q,11代表都包含
public int dfs(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return 0;
}
int state = dfs(root.left, p, q);
if (root == p) {
state |= 1;
} else if (root == q) {
state |= 2;
}
state |= dfs(root.right, p, q);
if (state == 3 && ans == null) {
ans = root;
}
return state;
}
}
class Solution {
public String addStrings(String num1, String num2) {
String res = "";
ArrayList<Integer> A = new ArrayList<>();
ArrayList<Integer> B = new ArrayList<>();
for (int i = num1.length() - 1; i >= 0; i--) {
A.add(num1.charAt(i) - '0');
}
for (int i = num2.length() - 1; i >= 0; i--) {
B.add(num2.charAt(i) - '0');
}
ArrayList<Integer> resList = add(A, B);
for (int i = resList.size() - 1; i >= 0; i--) {
res += String.valueOf(resList.get(i));
}
return res;
}
public ArrayList<Integer> add(ArrayList<Integer> A, ArrayList<Integer> B) {
ArrayList<Integer> res = new ArrayList<>();
int t = 0;
for (int i = 0; i < A.size() || i < B.size() || t != 0; i++) {
if (i < A.size()) {
t += A.get(i);
}
if (i < B.size()) {
t += B.get(i);
}
res.add(t % 10);
t /= 10;
}
return res;
}
}
/*
f[i]表示所有以nums[i]结尾的区间中的最大和是多少
f[i] = max{nums[i],f[i-1]+nums[i]} = nums[i] + max{0,f[i-1]}
实现过程中用last表示f[i-1]
*/
class Solution {
public int maxSubArray(int[] nums) {
int res = Integer.MIN_VALUE;
for (int i = 0, last = 0; i < nums.length; i++) {
last = nums[i] + Math.max(last, 0);
res = Math.max(res, last);
}
return res;
}
}
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA, q = headB;
while (p != q) {
p = p != null ? p.next : headB;
q = q != null ? q.next : headA;
}
return p;
}
}
class Solution {
public List<Integer> rightSideView(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
queue.add(root);
while (!queue.isEmpty()) {
int n = queue.size();
for (int i = 0; i < n; i++) {
TreeNode node = queue.remove();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
if (i == n - 1) {
res.add(node.val);
}
}
}
return res;
}
}
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (!stack.empty() && Math.abs(stack.peek() - c) <= 2) {
stack.pop();
} else {
return false;
}
}
}
return stack.empty();
}
}
// flood fill
class Solution {
private char[][] g;
private int[] dx = {0, 1, 0, -1}, dy = {-1, 0, 1, 0};
public int numIslands(char[][] grid) {
g= grid;
int cnt = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (g[i][j] == '1') {
dfs(i, j);
cnt++;
}
}
}
return cnt;
}
public void dfs(int x, int y) {
g[x][y] = 0;
for (int i = 0; i < 4; i++) {
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < g.length && b >= 0 && b < g[0].length && g[a][b] == '1') {
dfs(a, b);
}
}
}
}
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int k = m + n - 1;
int i = m - 1, j = n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while (j >= 0) {
nums1[k--] = nums2[j--];
}
}
}
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if(root != null){
dfs(root, targetSum);
}
return res;
}
public void dfs(TreeNode root, int sum){
path.add(root.val);
sum -= root.val;
if(root.left == null && root.right == null && sum == 0){
res.add(new ArrayList<>(path));
} else{
if(root.left != null){
dfs(root.left, sum);
}
if(root.right != null){
dfs(root.right, sum);
}
}
path.remove(path.size()-1);
}
}
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left), maxDepth(root.right))+1;
}
}
class Solution {
private int res = 0;
public int diameterOfBinaryTree(TreeNode root) {
dfs(root);
return res;
}
public int dfs(TreeNode root){
if(root == null){
return 0;
}
int left = dfs(root.left);
int right = dfs(root.right);
res = Math.max(res, left+right);
return Math.max(left,right)+1;
}
}
class Solution {
HashMap<Integer, Integer> pos = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i = 0; i < inorder.length; i++){
pos.put(inorder[i], i);
}
return build(preorder, inorder, 0, preorder.length-1, 0, inorder.length-1);
}
public TreeNode build(int[] preorder, int[] inorder, int pl, int pr, int il, int ir){
if(pl > pr){
return null;
}
TreeNode root = new TreeNode(preorder[pl]);
int k = pos.get(root.val);
root.left = build(preorder, inorder, pl+1, pl+1+k-1-il,il,k-1);
root.right = build(preorder, inorder,pl+1+k-1-il+1 ,pr,k+1,ir);
return root;
}
}
class Solution {
public int mySqrt(int x) {
int l = 0, r = x;
while(l < r){
int mid = l + (r-l)/2 + 1;
if(mid <= x/mid){
l = mid;
} else {
r = mid -1;
}
}
return l;
}
}
class Solution {
public int search(int[] nums, int target) {
if(nums.length == 0){
return -1;
}
int l = 0, r = nums.length-1;
while(l < r){
int mid = l+r+1>>1;
if(nums[mid] >= nums[0]){
l = mid;
} else {
r = mid -1;
}
}
if(target >= nums[0]){
l = 0;
} else {
l = r+1;
r = nums.length-1;
}
while(l < r){
int mid = l+r >> 1;
if(nums[mid] >= target){
r = mid;
} else {
l = mid +1;
}
}
if(nums[r] == target){
return r;
} else {
return -1;
}
}
}
//枚举每个位置填哪个数
class Solution {
private List<List<Integer>> ans = new ArrayList<>();
private ArrayList<Integer> path = new ArrayList<>();
private boolean[] st;
public List<List<Integer>> permute(int[] nums) {
st = new boolean[nums.length];
dfs(nums, 0);
return ans;
}
public void dfs(int[] nums, int u){
if(u == nums.length){
ans.add(new ArrayList<>(path));
return;
}
for(int i = 0; i < nums.length; i++){
if(st[i] == false){
path.add(nums[i]);
st[i] = true;
dfs(nums, u+1);
st[i] = false;
path.remove(path.size()-1);
}
}
}
}
class Solution {
private List<List<Integer>> ans = new ArrayList<>();
private ArrayList<Integer> path = new ArrayList<>();
private boolean[] state;
public List<List<Integer>> permuteUnique(int[] nums) {
state = new boolean[nums.length];
Arrays.sort(nums);
dfs(nums, 0);
return ans;
}
public void dfs(int[] nums, int u){
if(u == nums.length){
ans.add(new ArrayList<>(path));
return;
}
for(int i = 0; i < nums.length; i++){
if(!state[i]){
//判断nums[i]是否是按顺序第一次用
if(i > 0 && nums[i-1] == nums[i] && !state[i-1]){
continue;
}
path.add(nums[i]);
state[i] = true;
dfs(nums, u+1);
state[i] = false;
path.remove(path.size()-1);
}
}
}
}
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode p = head;
for(int i= 0; i < k-1 && p != null; i++){
p = p.next;
}
if(p == null){
return null;
}
ListNode q = head;
while(p.next != null){
q = q.next;
p = p.next;
}
return q;
}
}
class Solution {
private int ans = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
dfs(root);
return ans;
}
public int dfs(TreeNode u){
if(u == null){
return 0;
}
int left = Math.max(dfs(u.left),0);
int right = Math.max(dfs(u.right),0);
ans = Math.max(ans, u.val+left+right);
return u.val + Math.max(left,right);
}
}
class Solution {
private boolean ans;
public boolean isBalanced(TreeNode root) {
ans = true;
dfs(root);
return ans;
}
public int dfs(TreeNode root){
if(root == null){
return 0;
}
int left = dfs(root.left);
int right = dfs(root.right);
if(Math.abs(left-right) > 1){
ans = false;
}
return Math.max(left,right)+1;
}
}
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1), tail = dummy;
int t = 0;
while(l1 != null || l2 != null || t != 0){
if(l1 != null){
t += l1.val;
l1 = l1.next;
}
if(l2 != null){
t += l2.val;
l2 = l2.next;
}
tail = tail.next = new ListNode(t % 10);
t /= 10;
}
return dummy.next;
}
}
class MyQueue {
private Stack<Integer> stack1 = new Stack<>();
private Stack<Integer> stack2 = new Stack<>();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
stack1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
peek();
return stack2.pop();
}
/** Get the front element. */
public int peek() {
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
}
class MyStack {
private Queue<Integer> queue = new LinkedList<>();
/** Initialize your data structure here. */
public MyStack() {
}
/** Push element x onto stack. */
public void push(int x) {
int n = queue.size();
queue.add(x);
for(int i = 0; i < n; i++){
queue.add(queue.remove());
}
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue.remove();
}
/** Get the top element. */
public int top() {
return queue.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue.isEmpty();
}
}
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
int[] dx = {0,1,0,-1}, dy = {1,0,-1,0};
int n = matrix.length;
int m = matrix[0].length;
boolean[][] st = new boolean[n][m];
for(int i = 0, x = 0, y = 0, d = 0; i < m*n; i++){
res.add(matrix[x][y]);
st[x][y] = true;
int a = x + dx[d], b = y + dy[d];
if(a < 0 || a >= n || b < 0 || b >= m || st[a][b]){
d = (d+1) % 4;
a = x + dx[d];
b = y + dy[d];
}
x = a; y = b;
}
return res;
}
}
class Solution {
public String longestPalindrome(String s) {
String res = "";
for(int i = 0; i < s.length(); i++){
int l = i - 1, r = i + 1;
while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){
l--;
r++;
}
// (r-1)-(l+1)+1 = r-l-1
if(res.length() < r - l - 1){
res = s.substring(l+1, r);
}
l = i; r = i+1;
while(l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){
l--;
r++;
}
if(res.length() < r-l-1){
res = s.substring(l+1, r);
}
}
return res;
}
}