数据结构
算法
概念
链表
广度优先搜索
位操作
树、单词查找树、图
深度优先搜索
内存(堆、栈)
栈和队列
二分查找
递归
堆
归并排序
动态规划
向量、数组列表
快排
时间、空间复杂度
散列表
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。(要求线性时间复杂度,即$O(1)$)
实例:输入:[1,2,3,2,1] 输出:3
1 2 3 4 5 6 7 public int singleNumber (int [] nums) { int result = 0 ; for (int x : nums){ result = result ^ x; } return result; }
给定一个正整数,如何判断该数是否为2的幂次方?
实例:输入 32 输出 true
输入 25 输出 false
1 2 3 public boolean isMi (int num) { return num & (num -1 ) == 0 ; }
输入一颗二叉树,求树的深度 利用递归实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class TreeNode { int val = 0 ; TreeNode left = null ; TreeNode right = null ; public TreeNode (int val) { this .val = val; } }public class Solution { public int TreeDepth (TreeNode root) { if (root ==null ){ return 0 ; } return 1 + Math.max(TreeDepth(root.left),TreeDepth(root.right)); } }
不用加减乘除实现 加法 减法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Solution { public int Add (int num1,int num2) { if (num2==0 ){ return num1; } int res = num1 ^ num2; int res2 = (num1&num2) << 1 ; return Add(res,res2); } public int minus (int num1,int num2) { } }
二叉树镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Solution { public void Mirror (TreeNode root) { if (root == null ) return ; swap(root); Mirror(root.left); Mirror(root.right); } private void swap (TreeNode root) { TreeNode node = root.left; root.left= root.right; root.right = node; } }
两个栈实现队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Solution { Stack<Integer> in = new Stack<Integer>(); Stack<Integer> out = new Stack<Integer>(); public void push (int node) { in.push(node); } public int pop () { if (out.isEmpty()){ while (!in.isEmpty()){ out.push(in.pop()); } } return out.pop(); } }
两个队列实现一个栈
获取链表倒数第K个节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Solution { public ListNode FindKthToTail (ListNode head,int k) { if (head == null ){ return null } ListNode first = head; while (first!=null && k-->0 ){ first = first.next; } if (k>0 ){ return null ; } ListNode kNode = head; while (first!=null ){ first = first.next; kNode = kNode.next; } return kNode; } }
反转链表并输出表头
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 Solution { public ListNode ReverseList (ListNode head) { ListNode reverseList = new ListNode(-1 ); while (head!=null ){ ListNode next = head.next; head.next = reverseList.next; reverseList.next = head; reverseList = next; } return reverseList.next; } public ListNode ReverseList1 (ListNode head) { ListNode pre = null ; ListNode cur = head; ListNode next = null ; while (cur!=null ){ next = cur.next; cur.next = pre; pre = cur; cur = next; } return pre; } }
LeetCode 24:交换链表中节点
1 2 3 4 5 6 7 8 9 10 11 public class Solution { public ListNode swapPairs (ListNode head) { if (head==null || head.next ==null ) return head; ListNode next = head.next; head.next = swapPairs(next.next); next.next = head; reyurn next; } }
实现一个包含min()
的栈,可以返回栈中的最小值
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 Solution { private Stack<Integer> minStack = new Stack(); private Stack<Integer> inputStack = new Stack(); public void push (int node) { inputStack.push(node); minStack.push(minStack.isEmpty()?node:Math.min(minStack.peek(),node)); } public void pop () { inputStack.pop(); minStack.pop(); } public int top () { return inputStack.peek(); } public int min () { return minStack.peek(); } }
斐波那契数列
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Solution { public int Fibonacci (int n) { if (n<=1 ){ return n; } int [] fib = new int [n+1 ]; fib[1 ] = 1 ; for (int i=2 ;i<=n;i++){ fib[i] = fib[i-1 ]+fib[i-2 ]; } return fib[n]; } }
重建二叉树
已知前序遍历和中序遍历
> 例如 前序遍历为 {1,2,4,7,3,5,6,8} //根节点在前方 \> > 中序遍历为{4,7,2,1,5,3,8,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 public class Solution { private HashMap<Integer,Integer> map = new HashMap<>(); private int rootIndex ; public TreeNode buildTree (int [] pre,int [] in) { int len = in.length; for (int i=0 ;i<len;i++){ map.put(in[i],i); } rootIndex = 0 ; return buildTree(pre,0 ,len-1 ); } public TreeNode buildTree (int [] pre,int start,int end) { if (start>end){ return null ; } TreeNode rootNode = new TreeNode(pre[rootIndex++]) int index = map.get(rootNode.val); rootNode.left = buildTree(pre,start,index-1 ); rootNode.right = buildTree(pre,index+1 ,end); return rootNode; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Solution { private HashMap<Integer,Integer> map = new HashMap<>(); private int rootIndex; public TreeNode BuildTree (int [] post,int [] in) { int len = in.length; for (int i=0 ;i<len;i++){ map.put(in[i],i); } rootIndex = len-1 ; return buildTree(post,0 ,len-1 ); } public TreeNode buildTree (int [] post ,int start ,int end) { if (start>end) return null ; TreeNode rootNode = new TreeNode(post[rootIndex--]); int index = map.get(rootNode.val); rootNode.right = buildTree(post,index+1 ,end); rootNode.left = buildTree(post,start,index-1 ); return rootNode; } }
-
判断链表是否成环,若成环找出入口点
判断next是否为null,不为null则成环
利用Set
存储每个节点,每到新节点判断是否出现重复。时间复杂度O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Solution { public ListNode EntryNodeOfLoop (ListNode head) { if (head==null ) return null ; ListNode fast = head; ListNode slow = head; while (fast!=null && fast.next!=null ){ fast = fast.next.next; slow = slow.next; if (fast==slow){ ListNode result = head; while (head!=slow){ result = result.next; slow = slow.next; } return result; } } } }
删除链表中重复的节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Solution { public ListNode deleteDuplication (ListNode head) { if (head == null || head.next ==null ) return head; ListNode next = head.next; if (head.val == next.val){ while (next!=null && head.val == next.val) next = next.next; return deleteDuplication(next); }else { head.next = deleteDuplication(next); return head; } } }
判断是否为平衡二叉树
平衡二叉树:左子树和右子树高度相差不到1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Solution { private boolean isBalanced = true ; public boolean IsBalanced_Solution (TreeNode node) { return isBalanced; } private int getTreeHeight (TreeNode node) { if (node == null || !isBalanced){ return 0 ; } int left = getTreeHeight(node.left); int right = getTreeHeight(node.right); if (Math.abs(left-right)<1 ){ isBalanced = false ; } return 1 +Math.max(left,right); } }
字符流中第一个不重复字符串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 public class Solution { HashMap<Character,Integer> map = new LinkedHashMap(); char firstChar = "#" .charAt(0 ); public void Insert (char ch) { if (map.containsKey(ch)) { map.put(ch, 0 ); } else { map.put(ch, 1 ); } for (Map.Entry<Character, Integer> entry : map.entrySet()) { if (entry.getValue() == 1 ) { firstChar = entry.getKey(); break ; }else { firstChar = "#" .charAt(0 ); } } } public char FirstAppearingOnce () { return firstChar; } }
二叉搜索树的后序遍历序列 后序遍历过程: 左->右->中二叉搜索树
:设x是树中的一个节点,如果y是x左子树中的一个节点,那么y\<=x,如果y是x右子树的一个节点,那么y>=x1 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 public class Solution { public static boolean VerifySquenceOfBST (int [] sequence) { if (sequence.length ==0 || sequence==null ){ return false ; } if (sequence.length == 1 ){ return true ; } return search(sequence,0 ,sequence.length-1 ); } private static boolean search (int [] array ,int start,int end) { if (start > end){ return true ; } int i = end; while (i>start && array[i-1 ] > array[end]){ i--; } for (int j = i-1 ;j>=start;j--){ if (array[j] > array[end]){ return false ; } } return search(array,start,i-1 ) && search(array,i+1 ,end-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 public class Solution { private static ArrayList<ArrayList<Integer>> arrayLists = new ArrayList<>(); public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) { arrayLists.clear(); addPath(root,new ArrayList(),0 ,target); return arrayLists; } private static void addPath (TreeNode root, ArrayList<Integer> path, int num, int target) { if (root == null ) { return ; } num += root.val; path.add(root.val); if (root.left == null && root.right == null ) { if (num == target) { arrayLists.add(new ArrayList<>(path)); } } else { addPath(root.left, path, num, target); addPath(root.right, path, num, target); } path.remove(path.size() - 1 ); } }
实现一个LFU算法
淘汰一定时期内被访问次数最少的元素
Leetcode 703
采用优先队列机制实现,比较第K大元素问题 优先队列采用 小顶堆 小的数据放在根节点,这样在插入节点时只要与根节点比较即可1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class KthLargest { PriorityQueue<Integer> priorityQueue; int maxSize = 0 ; public KthLargest (int k, int [] nums) { this .maxSize = k; priorityQueue = new PriorityQueue<Integer>(k); for (int var : nums) { add(var ); } } public int add (int val) { if (priorityQueue.size() < maxSize) { priorityQueue.offer(val); } else if (priorityQueue.peek() < val) { priorityQueue.poll(); priorityQueue.offer(val); } return priorityQueue.peek(); } }
Leetcode 239:Sliding Window Maximum
Leetcode 15: 3Sum
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
解题思路:
先对数组进行排序,按照从小到大的顺序。将排序后的数组全部放入到HashMap
中
题目中要求a+b+c=0 ==> c=-a-b
即 在Map中找到-a-b
对应的值并取出即可
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 时间复杂度:`O(n2)`class Solution { public List<List<Integer>> threeSum(int [] nums) { List<List<Integer>> result = new ArrayList<>(); HashMap<Integer, Integer> set = new HashMap<>(); int len = nums.length; if (nums.length < 3 ) return result; Arrays.sort(nums); for (int i = 0 ; i < len; i++) { set.put(nums[i], i); } for (int i = 0 ; i < len; i++) { if (i != 0 && nums[i] == nums[i - 1 ]) continue ; for (int j = i + 1 ; j < len; j++) { if (nums[i] > 0 ) break ; if (nums[j] == nums[j - 1 ] && j != i + 1 ) continue ; if (set.containsKey(-nums[i] - nums[j]) && set.get(-nums[i] - nums[j]) > j) { List<Integer> l = new ArrayList<Integer>(); l.add(nums[i]); l.add(nums[j]); l.add(-nums[i] - nums[j]); result.add(l); } } } return result; } }
优化解法
还是先进行排序,固定首位数据a
,然后在剩下的数据内,设置下一位为b
,数组最后一位为c
,如果a+b+c=0
直接取出对应值,
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 class Solution { public List<List<Integer>> threeSum(int [] nums) { List<List<Integer>> result = new ArrayList<>(); int len = nums.length; if (nums.length < 3 ) return result; Arrays.sort(nums); for (int i = 0 ; i < len - 2 ; i++) { if (i > 0 && nums[i] == nums[i - 1 ]) continue ; int low = i + 1 ; int high = len - 1 ; while (low < high) { int resultNum = nums[i] + nums[low] + nums[high]; if (resultNum == 0 ) { List<Integer> l = new ArrayList<Integer>(); l.add(nums[i]); l.add(nums[low]); l.add(nums[high]); result.add(l); while (low < high && nums[low] == nums[low + 1 ]) low++; while (low < high && nums[high] == nums[high - 1 ]) high--; low++; high--; } else if (resultNum > 0 ) { high--; } else { low++; } } } return result; } }