├── .gitignore ├── gulpfile.js ├── tips ├── Char.md ├── Stack.md ├── HashMap.md ├── List.md ├── Queue.md ├── IO.md ├── Math.md ├── Array.md └── String.md ├── source └── leetcode │ ├── 50.Pow(x, n).md │ ├── 9.Palindrome Number.md │ ├── 100.Same Tree.md │ ├── 69.Sqrt(x).md │ ├── 136.Single Number.md │ ├── 344.Reverse String.md │ ├── 7.Reverse Integer.md │ ├── 104.Maximum Depth of Binary Tree.md │ ├── 141.Linked List Cycle.md │ ├── 101.Symmetric Tree.md │ ├── 83.Remove Duplicates from Sorted List.md │ ├── 70.Climbing Stairs.md │ ├── 14.Longest Common Prefix.md │ ├── 110.Balanced Binary Tree.md │ ├── 169.Majority Element.md │ ├── 108.Convert Sorted Array to Binary Search Tree.md │ ├── 111.Minimum Depth of Binary Tree.md │ ├── 24.Swap Nodes in Pairs.md │ ├── 53.Maximum Subarray.md │ ├── 137.Single Number II.md │ ├── 71.Simplify Path.md │ ├── 119.Pascal's Triangle II.md │ ├── 66.Plus One.md │ ├── 75.Sort Colors.md │ ├── 117.Populating Next Right Pointers in Each Node II.md │ ├── 88.Merge Sorted Array.md │ ├── 27.Remove Element.md │ ├── 121.Best Time to Buy and Sell Stock.md │ ├── 96.Unique Binary Search Trees.md │ ├── 61.Rotate List.md │ ├── 109.Convert Sorted List to Binary Search Tree.md │ ├── 112.Path Sum.md │ ├── 21.Merge Two Sorted Lists.md │ ├── 48.Rotate Image.md │ ├── 55.Jump Game.md │ ├── 35.Search Insert Position.md │ ├── 67. Add Binary.md │ ├── 62.Unique Paths.md │ ├── 26.Remove Duplicates from Sorted Array.md │ ├── 19.Remove Nth Node From End of List.md │ ├── 64.Minimum Path Sum.md │ ├── 106.Construct Binary Tree from Inorder and Postord.md │ ├── 77.Combinations.md │ ├── 105.Construct Binary Tree from Preorder and Inorder.md │ ├── 6.ZigZag Conversion.md │ ├── 125.Valid Palindrome.md │ ├── 58.Length of Last Word.md │ ├── 114.Flatten Binary Tree to Linked List.md │ ├── 34.Search for a Range.md │ ├── 41.First Missing Positive.md │ ├── 129.Sum Root to Leaf Numbers.md │ ├── 73.Set Matrix Zeroes.md │ ├── 36.Valid Sudoku.md │ ├── 120.Triangle.md │ ├── 80.Remove Duplicates from Sorted Array II.md │ ├── 118.Pascal's Triangle.md │ ├── 74.Search a 2D Matrix.md │ ├── 98.Validate Binary Search Tree.md │ ├── 11.Container With Most Water.md │ ├── 78.Subsets.md │ ├── 3.Longest Substring Without Repeating Characters.md │ ├── 82.Remove Duplicates from Sorted List II.md │ ├── 13.Roman to Integer.md │ ├── 92.Reverse Linked List II.md │ ├── 102.Binary Tree Level Order Traversal.md │ ├── 23.Merge k Sorted Lists.md │ ├── 1.Two Sum.md │ ├── 86.Partition List.md │ ├── 122.Best Time to Buy and Sell Stock II.md │ ├── 89.Gray Code.md │ ├── 63.Unique Paths II.md │ ├── 60.Permutation Sequence.md │ ├── 107.Binary Tree Level Order Traversal II.md │ ├── 42.Trapping Rain Water.md │ ├── 91.Decode Ways.md │ ├── 47.Permutations II.md │ ├── 113.Path Sum II.md │ ├── 22.Generate Parentheses.md │ ├── 8.String to Integer (atoi).md │ ├── 54.Spiral Matrix.md │ ├── 49.Group Anagrams.md │ ├── 103.Binary Tree Zigzag Level Order Traversal.md │ ├── 93.Restore IP Addresses.md │ ├── 16.3Sum Closest.md │ ├── 28.Implement strStr().md │ ├── 94.Binary Tree Inorder Traversal.md │ ├── 39.Combination Sum.md │ ├── 59.Spiral Matrix II.md │ ├── 116.Populating Next Right Pointers in Each Node.md │ ├── 2.Add Two Numbers.md │ ├── 43.Multiply Strings.md │ ├── 90.Subsets II.md │ ├── 40.Combination Sum II.md │ ├── 15.3Sum.md │ ├── 38.Count and Say.md │ ├── 31.Next Permutation.md │ ├── 18.4Sum.md │ ├── 46.Permutations.md │ ├── 20.Valid Parentheses.md │ ├── 79.Word Search.md │ ├── 17.Letter Combinations of a Phone Number.md │ ├── 4.Median of Two Sorted Arrays.md │ └── 5.Longest Palindromic Substring.md ├── package.json ├── generate.py ├── README.md ├── book.json └── SUMMARY.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .publish/ 4 | node_modules/ 5 | _book/ -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var deploy = require("gulp-gh-pages"); 2 | var gulp = require("gulp"); 3 | 4 | 5 | gulp.task('deploy', function () { 6 | return gulp.src("./_book/**/*").pipe(deploy()); 7 | }); -------------------------------------------------------------------------------- /tips/Char.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——字符类 2 | 3 | ### 字符转数字 4 | 5 | ```java 6 | // 方法一 7 | char ch = '1'; 8 | int value = Character.getNumericValue(ch); // => 1 9 | // 方法二 10 | char ch = '9'; 11 | int value = ch - '0'; // => 9 12 | ``` 13 | 14 | ### 数字转字符 15 | 16 | ```java 17 | int value = 3; 18 | char ch = value + '0'; // => '3' 19 | ``` -------------------------------------------------------------------------------- /tips/Stack.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——栈 2 | 3 | ### 标准库(java.util.Stack) 4 | ```java 5 | Stack stack = new Stack(); // => 泛型需要指定类型 6 | stack.isEmpty(); // => true 判断是否为空 7 | stack.empty(); // => true,在java中的实现为判断stack.size()是否为0 8 | stack.push('c'); 9 | stack.push('d'); // => 入栈操作 10 | stack.size(); // => 1,栈内有多少元素 11 | char ch = stack.peek(); // ch == 'd',获取栈顶元素 12 | ch = stack.pop(); // ch == 'd',出栈并返回栈顶元素 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /tips/HashMap.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——HashMap 2 | 3 | ### 基本用法 4 | ``` 5 | HashMap hash = new HashMap<>(); 6 | int key = 1001; 7 | int value = 1002232; 8 | hash.containsKey(key); // => false,是否包含某个键 9 | hash.containsValue(value); // => false,是否包含某个值 10 | hash.put(key, value); //=> 哈希表中添加键值对 11 | hash.remove(key); // 删除键为key的键值对 12 | hash.size(); // => 1, 大小 13 | hash.clear(); // 清空哈希表 14 | hash.isEmpty(); // => true, 判断是否为空 15 | hash.values(); // => [],返回值的集合 16 | ``` -------------------------------------------------------------------------------- /tips/List.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——List 2 | 3 | ## ArrayList 4 | ArrayList是一个类似于数组的List,对于只需要末尾添加元素和要求高效随机访问时使用 5 | 6 | ### ArrayList基本用法 7 | ```java 8 | List result = new ArrayList<>(); 9 | int tmp; 10 | int[] arr; 11 | result.add(1); // => [1],添加元素 12 | result.add(3); // => [1, 3],添加元素 13 | tmp = result.size(); // => 2,大小 14 | tmp = result.get(1); // => 3,返回该位置值 15 | tmp = result.set(0, 5); // => [5, 3], 设置 16 | tmp = result.remove(0); // => 5,删除并返回该位置值 17 | result.clear(); // => 清空 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /source/leetcode/50.Pow(x, n).md: -------------------------------------------------------------------------------- 1 | ### [Pow(x, n)](https://leetcode.com/problems/powx-n/) 2 | 3 | 题目难度:Medium 4 | 5 | ```java 6 | /** 7 | * Created by gzdaijie on 16/5/23 8 | * 判断二进制位上是否为1,若为1,乘上x对应的次方 9 | */ 10 | public class Solution { 11 | public double myPow(double x, int n) { 12 | double result = 1.0; 13 | for (long i = Math.abs((long)n); i > 0 ; i >>= 1, x *= x) { 14 | if ((i & 1) == 1) result *= x; 15 | } 16 | return n >= 0 ? result : 1/ result; 17 | } 18 | } 19 | ``` -------------------------------------------------------------------------------- /tips/Queue.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——队列 2 | 3 | ## Queue 4 | ### PriorityQueue(优先队列) 5 | ```java 6 | // 默认小值先出队,如果需要大值先出队,则重写比较函数,如下 7 | // 自定义类,则必须重写比较函数,升序大值优先,降序小值优先 8 | Queue queue = new PriorityQueue<>(10, new Comparator() { 9 | @Override 10 | public int compare(Integer o1, Integer o2) { 11 | if (o1 < o2) return 1; 12 | if (o1 > o2) return -1; 13 | return 0; 14 | } 15 | }); 16 | queue.add(5); 17 | queue.add(3); 18 | queue.offer(4); // 推荐使用offer而非add,poll而非remove,成否与否返回布尔值,不会抛异常 19 | queue.peek(); // => 5,取栈顶元素 20 | queue.poll(); // => 5,出队并返回栈顶元素 21 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leetcode-java", 3 | "version": "1.0.0", 4 | "description": "leetcode java exercise", 5 | "main": "gulpfile.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/gzdaijie/leetcode-java.git" 12 | }, 13 | "author": "gzdaijie@163.com", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/gzdaijie/leetcode-java/issues" 17 | }, 18 | "dependencies": { 19 | "gulp": "^3.9.1", 20 | "gulp-gh-pages": "^0.5.4" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.stdout = open('SUMMARY.md', 'w') 5 | 6 | # leetcode pages 7 | leetcode_pages = [path for path in os.listdir('source/leetcode')] 8 | leetcode_pages.sort(key=lambda x: int(x.split('.')[0])) 9 | print('Leetcode Java') 10 | print("* Leetcode练习题") 11 | for page in leetcode_pages: 12 | print(" * [%s](source/leetcode/%s)" % (page[:-3], page)) 13 | 14 | # java pages 15 | java_pages = [path for path in os.listdir('tips')] 16 | java_pages.sort() 17 | print('* Java类库') 18 | for i, page in enumerate(java_pages): 19 | print(" * [%d. %s](tips/%s)" % (i + 1,page[:-3], page)) 20 | 21 | sys.stdout.close() 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Leetcode Java算法练习 2 | 记录刷题过程的点滴 3 | 4 | ## 常用类库总结 5 | 6 | - [输入输出 IO](tips/IO.md) 7 | - [数组 Array](tips/Array.md) 8 | - [字符 IO](tips/Char.md) 9 | - [字符串 String](tips/String.md) 10 | - [数学 Math](tips/Math.md) 11 | - [栈 Stack](tips/Stack.md) 12 | - [队列 Queue](tips/Queue.md) 13 | - [哈希表 HashMap](tips/HashMap.md) 14 | 15 | ## 关于 16 | 17 | - Leetcode地址: [https://leetcode.com/problemset/algorithms](https://leetcode.com/problemset/algorithms/) 18 | - Github地址: [https://github.com/geektutu/leetcode-java](https://github.com/geektutu/leetcode-java) 19 | - Gitbook地址: [https://geektutu.github.io/leetcode-java/](https://geektutu.github.io/leetcode-java/) 20 | - 极客兔兔的小站: [https://geektutu.com](https://geektutu.com/series) 21 | -------------------------------------------------------------------------------- /source/leetcode/9.Palindrome Number.md: -------------------------------------------------------------------------------- 1 | ### [Palindrome Number](https://leetcode.com/problems/palindrome-number/) 2 | 3 | > Determine whether an integer is a palindrome. Do this without extra space. 4 | 5 | 题目大意:判断一个数字时候是回文,不允许有额外的空间 6 | 7 | 题目难度:Easy 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/5/4 12 | * 与第七题是相同的,判断翻转后的数字是否等于原来的数字即可 13 | * 担心翻转后溢出,故使用了long 14 | */ 15 | public class Solution { 16 | public boolean isPalindrome(int x) { 17 | if (x < 0) return false; 18 | 19 | long y = x; 20 | long result = 0; 21 | while (x > 0) { 22 | result = result * 10 + x % 10; 23 | x /= 10; 24 | } 25 | return result == y; 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /source/leetcode/100.Same Tree.md: -------------------------------------------------------------------------------- 1 | ### [Same Tree](https://leetcode.com/problems/same-tree/) 2 | 3 | > Given two binary trees, write a function to check if they are equal or not.
4 | > Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 5 | 6 | 题目大意:判断两个二叉树是否相同(形态与节点值相同) 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/7 13 | */ 14 | public class Solution { 15 | public boolean isSameTree(TreeNode p, TreeNode q) { 16 | if (p == null && q == null) return true; 17 | if (p == null || q == null) return false; 18 | return (p.val == q.val) && isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 19 | } 20 | } 21 | ``` -------------------------------------------------------------------------------- /source/leetcode/69.Sqrt(x).md: -------------------------------------------------------------------------------- 1 | ### [Sqrt(x)](https://leetcode.com/problems/sqrtx/) 2 | 3 | > Implement int sqrt(int x).
4 | > Compute and return the square root of x. 5 | 6 | 题目大意:计算x的平方根 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/30 13 | * 二分尝试 14 | */ 15 | public class Solution { 16 | public int mySqrt(int x) { 17 | long end = x; 18 | long start = 0; 19 | 20 | while (true) { 21 | long t = (start + end) / 2; 22 | long min = t * t; 23 | long max = (t + 1)* (t + 1); 24 | if (min <= x && max > x) return (int) t; 25 | if (max <=x) start = t + 1; 26 | else end = t; 27 | } 28 | } 29 | } 30 | ``` -------------------------------------------------------------------------------- /source/leetcode/136.Single Number.md: -------------------------------------------------------------------------------- 1 | ### [Single Number](https://leetcode.com/problems/single-number/) 2 | 3 | > Given an array of integers, every element appears twice except for one.
4 | > Find that single one.
5 | > Note:
6 | > Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 7 | 8 | 题目大意:给定一个数组,只有一个数出现过1次,其余均出现过2次,找出出现过一次的数 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/6/15 15 | */ 16 | public class Solution { 17 | public int singleNumber(int[] nums) { 18 | int result = 0; 19 | for (int i = 0; i < nums.length; i++) { 20 | result ^= nums[i]; 21 | } 22 | return result; 23 | } 24 | } 25 | ``` -------------------------------------------------------------------------------- /source/leetcode/344.Reverse String.md: -------------------------------------------------------------------------------- 1 | ### [Reverse String](https://leetcode.com/problems/reverse-string/) 2 | 3 | > Write a function that takes a string as input and returns the string reversed. 4 | 5 | 题目大意:翻转一个字符串 6 | 7 | 题目难度:Easy 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/5/5 12 | */ 13 | public class Solution { 14 | public String reverseString(String s) { 15 | if (s == null) return null; 16 | char arr[] = s.toCharArray(); 17 | int mid = arr.length/2; 18 | for (int i = 0; i < mid; i++) { 19 | char ch = arr[i]; 20 | arr[i] = arr[arr.length - i - 1]; 21 | arr[arr.length - i - 1] = ch; 22 | } 23 | return String.valueOf(arr); 24 | } 25 | } 26 | ``` -------------------------------------------------------------------------------- /source/leetcode/7.Reverse Integer.md: -------------------------------------------------------------------------------- 1 | ### [Reverse Integer](https://leetcode.com/problems/reverse-integer/) 2 | 3 | > Reverse digits of an integer.
4 | > Example1: x = 123, return 321 Example2: x = -123, return -321 5 | 6 | 题目大意:翻转整数,123 => 321,-123 => -321 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/4 13 | * 翻转,求余进位即可,处理溢出的情况 14 | */ 15 | public class Solution { 16 | public int reverse(int x) { 17 | long result = 0; 18 | while (x != 0) { 19 | result = result * 10 + x % 10; 20 | if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) { 21 | return 0; 22 | } 23 | x /= 10; 24 | } 25 | return (int)result; 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /source/leetcode/104.Maximum Depth of Binary Tree.md: -------------------------------------------------------------------------------- 1 | ### [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) 2 | 3 | > Given a binary tree, find its maximum depth.
4 | > The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 5 | 6 | 题目大意:计算给定二叉树的深度,非空根节点深度为1 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/7 13 | */ 14 | public class Solution { 15 | public int maxDepth(TreeNode root) { 16 | return helper(root, 0); 17 | } 18 | 19 | private int helper(TreeNode root, int depth) { 20 | if (root == null) return depth; 21 | return Math.max(helper(root.left, depth + 1), helper(root.right, depth + 1)); 22 | } 23 | } 24 | ``` -------------------------------------------------------------------------------- /source/leetcode/141.Linked List Cycle.md: -------------------------------------------------------------------------------- 1 | ### [Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) 2 | 3 | > Given a linked list, determine if it has a cycle in it.
4 | > Follow up: Can you solve it without using extra space? 5 | 6 | 题目大意:判断一个给定链表是否存在环 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/17 13 | * 两个指针从头开始走,一个一次走一步,另一个一次走2步,如果存在环,必定会相遇 14 | */ 15 | public class Solution { 16 | public boolean hasCycle(ListNode head) { 17 | if (head == null || head.next == null) return false; 18 | 19 | ListNode faster = head.next; 20 | while (faster.next != null && faster.next.next != null) { 21 | if (head == faster) return true; 22 | head = head.next; 23 | faster = faster.next.next; 24 | } 25 | return false; 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /tips/IO.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——输入输出类 2 | 3 | ### 基本类库 4 | ```java 5 | import java.io.*; 6 | import java.util.*; 7 | import java.math.*; 8 | ``` 9 | 10 | > 参考:[java在ACM中的使用](http://blog.csdn.net/sssogs/article/details/8526384) 11 | 12 | ### 读取数据 13 | ```java 14 | Scanner cin=new Scanner(System.in); 15 | // 或 Scanner cin=new Scanner(new BufferedInputStream(System.in)); 16 | int n; 17 | n = cin.nextInt(); 18 | System.out.println(n); 19 | ``` 20 | 21 | ### 输出结果 22 | ```java 23 | int n = 10 24 | System.out.println("Hello,ACM"); //自带换行符 25 | System.out.print(n); // 不带换行符 26 | ``` 27 | 28 | ### 标准输入输出重定向 29 | ```java 30 | // 获取当前类所在的路径 31 | FirstApp.class.getResource("/").getFile() 32 | // 输入(System.in)重定向到文件 33 | System.setIn(new FileInputStream("filePath")); 34 | // 输出(System.out)重定向到文件 35 | System.setOut(new PrintStream(new FileOutputStream("filePath"))); 36 | ``` -------------------------------------------------------------------------------- /tips/Math.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——数学类 2 | 3 | ### 高精度(java.math.BigInteger) 4 | 1. 加减乘除余 5 | 6 | ```java 7 | BigInteger a1 = new BigInteger("233"); 8 | BigInteger a2 = new BigInteger("10"); 9 | BigInteger result; 10 | result = a1.add(a2); // => 243 11 | result = a1.multiply(a2); // => 2430 12 | result = a1.subtract(a2); // => 223 13 | result = a1.divide(a2); // => 23 14 | result = a1.mod(a2); // => 3 15 | ``` 16 | 17 | 2. 打印与转换 18 | 19 | ```java 20 | BigInteger a1 = new BigInteger("233"); 21 | String s = a1.toString(); // => "233",转换为字符串 22 | System.out.println(a1); // => 233,可直接输出 23 | ``` 24 | 25 | 3.比较 26 | 27 | ```java 28 | int value; 29 | value = a1.compareTo(a2); // 1, 前者大于后者 返回1 30 | value = a2.compareTo(a1); // -1, 前者小于后者,返回 -1 31 | value = a1.compareTo(a1); // 0, 数值上相等,则返回0 32 | ``` 33 | 34 | 35 | -------------------------------------------------------------------------------- /source/leetcode/101.Symmetric Tree.md: -------------------------------------------------------------------------------- 1 | ### [Symmetric Tree](https://leetcode.com/problems/symmetric-tree/) 2 | 3 | > Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
4 | > For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
5 | > 1
6 | > / \
7 | > 2 2
8 | > / \ / \
9 | > 3 4 4 3 10 | 11 | 题目大意:判断给定二叉树是否是对称的 12 | 13 | 题目难度:Easy 14 | 15 | ```java 16 | /** 17 | * Created by gzdaijie on 16/6/7 18 | */ 19 | public class Solution { 20 | public boolean isSymmetric(TreeNode root) { 21 | return helper(root, root); 22 | } 23 | private boolean helper(TreeNode p, TreeNode q) { 24 | if (p == null && q == null) return true; 25 | if (p == null || q == null) return false; 26 | return p.val == q.val && helper(p.left, q.right) && helper(p.right, q.left); 27 | } 28 | } 29 | ``` -------------------------------------------------------------------------------- /source/leetcode/83.Remove Duplicates from Sorted List.md: -------------------------------------------------------------------------------- 1 | ### [Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) 2 | 3 | > Given a sorted linked list, delete all duplicates such that each element appear only once.
4 | > For example,
5 | > Given 1->1->2, return 1->2.
6 | > Given 1->1->2->3->3, return 1->2->3. 7 | 8 | 题目大意:给定一个链表,删除重复元素 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/6/4 15 | */ 16 | public class Solution { 17 | public ListNode deleteDuplicates(ListNode head) { 18 | if (head == null || head.next == null) return head; 19 | ListNode p = head.next; 20 | ListNode h = head; 21 | 22 | while (p != null) { 23 | if (p.val != h.val) h = h.next = p; 24 | p = p.next; 25 | } 26 | h.next = null; 27 | return head; 28 | } 29 | } 30 | ``` -------------------------------------------------------------------------------- /tips/Array.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——数组类 2 | 3 | ### 数组的排序 4 | ```java 5 | Arrays.sort(Type[] a, int fromIndex, int toIndex) 6 | ``` 7 | 8 | ### 数组的复制 9 | ```java 10 | // 方法一 11 | System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length); 12 | // 方法二 13 | int[] targetArray = (int[])sourceArray.clone(); // 返回是一个对象,需要强制类型转换 14 | ``` 15 | 16 | ### Array 与 ArrayList的相互转换 17 | ```java 18 | // int/Integer 19 | List list = Arrays.asList(1,2,3,4); // => ArrayList: [1,2,3,4] 20 | Integer[] arr = {1,2,3}; // arr不能是int[],否则,arr将当作一个int[]对象处理 21 | List list = Arrays.asList(arr); // => ArrayList: [1,2,3,4] 22 | Integer[] intArr = (Integer[])list.toArray(); // => Integer[]: [1,2,3,4] 23 | ``` 24 | 25 | ```java 26 | // String 27 | String[] strs = {"abc", "def"}; 28 | List list = Arrays.asList(strs); // => ArrayList: ["abc", "def"] 29 | String[] strArr = (String[]) list.toArray(); // => String[]: ["abc", "def"] 30 | ``` -------------------------------------------------------------------------------- /source/leetcode/70.Climbing Stairs.md: -------------------------------------------------------------------------------- 1 | ### [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/) 2 | 3 | > You are climbing a stair case. It takes n steps to reach to the top.
4 | > Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 5 | 6 | 题目大意:爬n级楼梯,每次可以爬1或2级,问有多少种不同的爬法 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/30 13 | * 假设有i个2,j个1,那么可能有 (i + j)!/(i! * j!)种 14 | * 因此考虑可以拆分为多少个2和1即可。 15 | */ 16 | public class Solution { 17 | public int climbStairs(int n) { 18 | int result = 0; 19 | for (int i = 0; i <= n/2; i++) { 20 | int count = n - i; 21 | long tmp = 1, k = 1; 22 | for (int j = n - 2 * i + 1; j <= count ; j++) { 23 | tmp *= j; 24 | tmp /= k++; 25 | } 26 | result += tmp; 27 | } 28 | return result; 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /source/leetcode/14.Longest Common Prefix.md: -------------------------------------------------------------------------------- 1 | [Longest Common Prefix](https://leetcode.com/problems/longest-common-prefix/) 2 | 3 | > Write a function to find the longest common prefix string amongst an array of strings. 4 | 5 | 题目大意:求给定字符串数组的最长相同前缀 6 | 7 | 题目难度:Easy 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/5/5 12 | * 复杂度 O(K*N) 13 | */ 14 | public class Solution { 15 | public String longestCommonPrefix(String[] strs) { 16 | if (strs.length == 0 ) return ""; 17 | 18 | int len = strs[0].length(); 19 | char[] result = new char[len]; 20 | int i; 21 | for (i = 0; i < len; i++) { 22 | int j; 23 | for (j = 1; j < strs.length; j++) { 24 | if (strs[j].length() <= i)break; 25 | if (strs[j].charAt(i) != strs[0].charAt(i))break; 26 | } 27 | if (j != strs.length)break; 28 | } 29 | return strs[0].substring(0,i); 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /source/leetcode/110.Balanced Binary Tree.md: -------------------------------------------------------------------------------- 1 | ### [Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) 2 | 3 | > Given a binary tree, determine if it is height-balanced.
4 | > For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 5 | 6 | 题目大意:判断给定二叉树是不是平衡二叉树 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/9 13 | */ 14 | public class Solution { 15 | public boolean isBalanced(TreeNode root) { 16 | return helper(root) >= 0; 17 | } 18 | 19 | private int helper(TreeNode root) { 20 | if (root == null) return 0; 21 | int left, right; 22 | 23 | left = helper(root.left); 24 | if (left < 0) return -1; 25 | right = helper(root.right); 26 | if (right < 0 || Math.abs(left - right) > 1) return -1; 27 | return Math.max(left, right) + 1; 28 | } 29 | } 30 | ``` -------------------------------------------------------------------------------- /source/leetcode/169.Majority Element.md: -------------------------------------------------------------------------------- 1 | ### [Majority Element](https://leetcode.com/problems/majority-element/) 2 | 3 | > Given an array of size n, find the majority element.
4 | > The majority element is the element that appears more than ⌊ n/2 ⌋ times.
5 | > You may assume that the array is non-empty and the majority element always exist in the array. 6 | 7 | 题目大意:找出数组中出现次数超过一半的数 8 | 9 | 题目难度:Easy 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/6/19 14 | */ 15 | public class Solution { 16 | public int majorityElement(int[] nums) { 17 | int cnt = 1; 18 | int result = nums[0]; 19 | for (int i = 1; i < nums.length; i++) { 20 | if (nums[i] == result) cnt++; 21 | else { 22 | cnt--; 23 | if (cnt == 0) { 24 | result = nums[i]; 25 | cnt = 1; 26 | } 27 | } 28 | } 29 | return result; 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /source/leetcode/108.Convert Sorted Array to Binary Search Tree.md: -------------------------------------------------------------------------------- 1 | ### [Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) 2 | 3 | > Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 4 | 5 | 题目大意:给定排好序的数组,构造二叉搜索树 6 | 7 | 题目难度:Medium 8 | 9 | ```java 10 | import java.util.*; 11 | /** 12 | * Created by gzdaijie on 16/6/8 13 | * 递归地将数组划分为左右2个部分,分别作为左子树和右子树 14 | */ 15 | public class Solution { 16 | public TreeNode sortedArrayToBST(int[] nums) { 17 | return helper(nums, 0, nums.length - 1); 18 | } 19 | 20 | public TreeNode helper(int[] nums, int start, int end) { 21 | if (start > end) return null; 22 | 23 | int mid = (start + end) / 2; 24 | TreeNode node = new TreeNode(nums[mid]); 25 | 26 | node.left = helper(nums, start, mid - 1); 27 | node.right = helper(nums, mid + 1, end); 28 | return node; 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /source/leetcode/111.Minimum Depth of Binary Tree.md: -------------------------------------------------------------------------------- 1 | ### [Minimum Depth of Binary Tree](https://leetcode.com/problems/minimum-depth-of-binary-tree/) 2 | 3 | > Given a binary tree, find its minimum depth.
4 | > The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 5 | 6 | 题目大意:返回给定二叉树的最小深度 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/9 13 | */ 14 | public class Solution { 15 | public int minDepth(TreeNode root) { 16 | return root == null ? 0 : helper(root, 1); 17 | } 18 | 19 | private int helper(TreeNode root, int depth) { 20 | if (root.left == null && root.right == null) return depth; 21 | 22 | int left = Integer.MAX_VALUE, right = Integer.MAX_VALUE; 23 | if (root.left != null) left = helper(root.left, depth + 1); 24 | if (root.right != null) right = helper(root.right, depth + 1); 25 | 26 | return Math.min(left, right); 27 | } 28 | } 29 | ``` -------------------------------------------------------------------------------- /source/leetcode/24.Swap Nodes in Pairs.md: -------------------------------------------------------------------------------- 1 | ### [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/) 2 | 3 | > Given a linked list, swap every two adjacent nodes and return its head.
4 | > For example, Given 1->2->3->4, you should return the list as 2->1->4->3. 5 | 6 | 题目大意:给定链表,交换相邻的2个节点,例如1->2->3->4,交换之后是2->1->4->3,要求空间复杂度O(1),不能改变节点值 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/6 13 | * 加一个头指针,操作会更方便 14 | * 当 p.next 和 p.next.next 非空时,交换;p后移2位 15 | * 这道题考察的是改变指针指向,实现链表节点位置交换 16 | */ 17 | public class Solution { 18 | public ListNode swapPairs(ListNode head) { 19 | ListNode h = new ListNode(-1); 20 | ListNode p = h, q; 21 | h.next = head; 22 | 23 | while (p.next != null && p.next.next!= null) { 24 | q = p.next; 25 | p.next = q.next; 26 | q.next = p.next.next; 27 | p.next.next = q; 28 | p = p.next.next; 29 | } 30 | return h.next; 31 | } 32 | } 33 | ``` -------------------------------------------------------------------------------- /source/leetcode/53.Maximum Subarray.md: -------------------------------------------------------------------------------- 1 | ### [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) 2 | 3 | > Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
4 | > For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
5 | > the contiguous subarray [4,−1,2,1] has the largest sum = 6. 6 | 7 | 题目大意:给定数组,返回连续子数组的最大和。 8 | 9 | 题目难度:Medium 10 | 11 | ```java 12 | import java.util.*; 13 | /** 14 | * Created by gzdaijie on 16/5/25 15 | * 时间复杂度O(N),sum记录临时和,发现sum为负数为置为0,因为为负数,舍去前面的值和更大 16 | */ 17 | public class Solution { 18 | public int maxSubArray(int[] nums) { 19 | if (nums == null || nums.length == 0) return 0; 20 | int len = nums.length; 21 | int result = nums[0]; 22 | int sum = 0; 23 | 24 | for (int i = 0; i < len; i++) { 25 | sum += nums[i]; 26 | result = Math.max(result, sum); 27 | sum = Math.max(0, sum); 28 | } 29 | return result; 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /source/leetcode/137.Single Number II.md: -------------------------------------------------------------------------------- 1 | ### [Single Number II](https://leetcode.com/problems/single-number-ii/) 2 | 3 | > Given an array of integers, every element appears three times except for one. Find that single one.
4 | > Note:
5 | > * Your algorithm should have a linear runtime complexity.
6 | > * Could you implement it without using extra memory? 7 | 8 | 题目大意:给定一个数组,除了一个数以外其余所有数都出现了三次,找出该数。要求事件复杂度O(N),空间复杂度O(1) 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/6/18 15 | * 记录每一个int位出现的次数,若是三的倍数,说明出现了三次 16 | */ 17 | public class Solution { 18 | public int singleNumber(int[] nums) { 19 | int[] tag = new int[32]; 20 | int result = 0; 21 | 22 | for (int i = 0; i < 32; i++) { 23 | for (int j = 0; j < nums.length; j++) { 24 | tag[i] += (nums[j] >> i) & 1; 25 | } 26 | } 27 | for (int i = 0; i < 32; i++) { 28 | if (tag[i] % 3 != 0) result += 1 << i; 29 | } 30 | 31 | return result; 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /source/leetcode/71.Simplify Path.md: -------------------------------------------------------------------------------- 1 | ### [Simplify Path](https://leetcode.com/problems/simplify-path/) 2 | 3 | > Given an absolute path for a file (Unix-style), simplify it.
4 | > For example,
5 | > path = "/home/", => "/home"
6 | > path = "/a/./b/../../c/", => "/c" 7 | 8 | 题目大意:给定unix路径,返回简化后的路径 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/30 15 | */ 16 | public class Solution { 17 | public String simplifyPath(String path) { 18 | String[] strs = path.split("/"); 19 | int k = 0; 20 | for (int i = 0; i < strs.length; i++) { 21 | if (strs[i].equals("")) continue; 22 | if (strs[i].equals(".")) continue; 23 | if (strs[i].equals("..")) { 24 | if (k > 0) k--; 25 | } 26 | else strs[k++] = strs[i]; 27 | } 28 | 29 | String result = ""; 30 | for (int i = 0; i < k ; i++) { 31 | result += "/" + strs[i]; 32 | } 33 | return result.equals("") ? "/" : result; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /source/leetcode/119.Pascal's Triangle II.md: -------------------------------------------------------------------------------- 1 | ### [Pascal's Triangle II](https://leetcode.com/problems/pascals-triangle-ii/) 2 | 3 | > Given an index k, return the kth row of the Pascal's triangle.
4 | > For example, given k = 3,
5 | > Return [1,3,3,1].
6 | > Note: Could you optimize your algorithm to use only O(k) extra space? 7 | 8 | 题目大意:给定k,返回杨辉三角的第k行,空间复杂度要求O(K) 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | import java.util.*; 14 | 15 | /** 16 | * Created by gzdaijie on 16/6/11 17 | */ 18 | public class Solution { 19 | public List getRow(int rowIndex) { 20 | Queue result = new LinkedList<>(); 21 | result.offer(1); 22 | 23 | for (int i = 0; i < rowIndex; i++) { 24 | int size = result.size(); 25 | int pre = 0; 26 | while (size-- > 0) { 27 | int top = result.poll(); 28 | result.offer(pre + top); 29 | pre = top; 30 | } 31 | result.add(1); 32 | } 33 | return (List)result; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /source/leetcode/66.Plus One.md: -------------------------------------------------------------------------------- 1 | ### [Plus One](https://leetcode.com/problems/plus-one/) 2 | 3 | > Given a non-negative number represented as an array of digits, plus one to the number.
4 | > The digits are stored such that the most significant digit is at the head of the list. 5 | 6 | 题目大意:给定一个非负整数(以数组方式给出,各个位置为一位,最高位在第0位),加1后以数组形式返回结果 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/9 13 | */ 14 | public class Solution { 15 | public int[] plusOne(int[] digits) { 16 | if (digits == null || digits.length == 0) return null; 17 | 18 | int len = digits.length; 19 | while ( --len >= 0) { 20 | if (len == 0 && digits[0] == 9) { 21 | int[] result = new int[digits.length + 1]; 22 | result[0] = 1; 23 | return result; 24 | } 25 | if (digits[len] == 9) { 26 | digits[len] = 0; 27 | } else { 28 | ++digits[len]; 29 | break; 30 | } 31 | } 32 | return digits; 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /source/leetcode/75.Sort Colors.md: -------------------------------------------------------------------------------- 1 | ### [Sort Colors](https://leetcode.com/problems/sort-colors/) 2 | 3 | > Given an array with n objects colored red, white or blue,
4 | > sort them so that objects of the same color are adjacent,
5 | > with the colors in the order red, white and blue.
6 | > Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. 7 | 8 | 9 | 题目大意:给定一个数组,数组只包含数字0,1,2,对数组排序,不能使用内置排序函数 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | /** 15 | * Created by gzdaijie on 16/5/30 16 | * 桶排序,时间复杂度O(N) 17 | */ 18 | public class Solution { 19 | public void sortColors(int[] nums) { 20 | if (nums == null || nums.length < 2) return; 21 | 22 | int len = nums.length; 23 | int[] count = new int[3]; 24 | int k = 0; 25 | 26 | for (int i = 0; i < len; i++) count[nums[i]]++; 27 | 28 | for (int i = 0; i < count[0]; i++) nums[k++] = 0; 29 | for (int i = 0; i < count[1]; i++) nums[k++] = 1; 30 | for (int i = 0; i < count[2]; i++) nums[k++] = 2; 31 | } 32 | } 33 | ``` -------------------------------------------------------------------------------- /source/leetcode/117.Populating Next Right Pointers in Each Node II.md: -------------------------------------------------------------------------------- 1 | ### [Populating Next Right Pointers in Each Node II](https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/) 2 | 3 | > Follow up for problem "Populating Next Right Pointers in Each Node". 4 | 5 | 题目大意:与116题一致,但不是满二叉树 6 | 7 | 题目难度:Hard 8 | 9 | ```java 10 | import java.util.*; 11 | 12 | /** 13 | * Created by gzdaijie on 16/6/9 14 | */ 15 | public class Solution { 16 | public void connect(TreeLinkNode root) { 17 | Queue queue = new LinkedList<>(); 18 | if (root == null) return; 19 | 20 | queue.offer(root); 21 | while (!queue.isEmpty()) { 22 | int size = queue.size(); 23 | TreeLinkNode pre = null, p; 24 | while (size-- > 0) { 25 | p = queue.poll(); 26 | if (pre != null) pre.next = p; 27 | pre = p; 28 | if (p.left != null) queue.offer(p.left); 29 | if (p.right != null) queue.offer(p.right); 30 | } 31 | } 32 | } 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /source/leetcode/88.Merge Sorted Array.md: -------------------------------------------------------------------------------- 1 | ### [Merge Sorted Array](https://leetcode.com/problems/merge-sorted-array/) 2 | 3 | > Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
4 | > Note:
5 | > You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2.
6 | > The number of elements initialized in nums1 and nums2 are m and n respectively. 7 | 8 | 题目大意:nums1和nums2为2个已经排好序的数组,将nums2合并到nums1中,nums1有足够的空间 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/6/4 15 | * 因为nums1有足够的空间,所以选择从大到小合并 16 | * 时间复杂度O(N),空间复杂度O(1) 17 | */ 18 | public class Solution { 19 | public void merge(int[] nums1, int m, int[] nums2, int n) { 20 | int k = m + n; 21 | m--; n--; 22 | while (--k >= 0) { 23 | if (n < 0) return; // nums2已经合并完成 24 | if (m >= 0 && nums1[m] >= nums2[n]) { 25 | nums1[k] = nums1[m--]; 26 | } else { 27 | nums1[k] = nums2[n--]; 28 | } 29 | } 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /source/leetcode/27.Remove Element.md: -------------------------------------------------------------------------------- 1 | ### [Remove Element](https://leetcode.com/problems/remove-element/) 2 | 3 | > Given an array and a value, remove all instances of that value in place and return the new length.
4 | > Do not allocate extra space for another array, you must do this in place with constant memory.
5 | > The order of elements can be changed. It doesn't matter what you leave beyond the new length. 6 | 7 | 题目大意:给定未排序数组和一个数val,在数组中移除与val相等的所有实例,返回新的长度len。要求空间复杂度O(1),数组元素顺序可以变,允许数组有剩余元素,前len个数不包含val即可。 8 | 9 | 题目难度:Easy 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/8 14 | */ 15 | public class Solution { 16 | public int removeElement(int[] nums, int val) { 17 | if (nums == null || nums.length == 0) return 0; 18 | 19 | int len = nums.length; 20 | int k = 0; 21 | for (int i = 0; i < len; i++) { 22 | // 不相同时,更新nums[k] 和 k, 仅在k!=i时更新nums[k],避免不必要赋值 23 | if (nums[i] != val) { 24 | if (k != i) nums[k] = nums[i]; 25 | ++k; 26 | } 27 | } 28 | return k; 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /source/leetcode/121.Best Time to Buy and Sell Stock.md: -------------------------------------------------------------------------------- 1 | ### [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) 2 | 3 | > Say you have an array for which the ith element is the price of a given stock on day i.
4 | > If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit. 5 | 6 | 题目大意:给定一个数组,代表股票每天的价格,假设至多只能买卖一次,找出最大利润 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/11 13 | * 每次更新最低价格 min,之后用 prices[i] - min 更新 result 14 | * 实质是寻找满足i > j的 prices[i] - prices[j] 的最大值 15 | */ 16 | public class Solution { 17 | public int maxProfit(int[] prices) { 18 | if (prices == null || prices.length < 2) return 0; 19 | 20 | int len = prices.length; 21 | int min = prices[0]; 22 | int result = 0; 23 | 24 | for (int i = 1; i < len; i++) { 25 | if (prices[i] <= min) min = prices[i]; 26 | else result = Math.max(result, prices[i] - min); 27 | } 28 | return result; 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /source/leetcode/96.Unique Binary Search Trees.md: -------------------------------------------------------------------------------- 1 | ### [Unique Binary Search Trees](https://leetcode.com/problems/unique-binary-search-trees/) 2 | 3 | > Given n, how many structurally unique BST's (binary search trees) that store values 1...n?
4 | > For example,
5 | > Given n = 3, there are a total of 5 unique BST's.
6 | > 1 3 3 2 1
7 | > \ / / / \ \
8 | > 3 2 1 1 3 2
9 | > / / \ \
10 | > 2 1 2 3 11 | 12 | 题目大意:给定数字n,有多少种包含数字1->n的二叉搜索树。 13 | 14 | 题目难度:Medium 15 | 16 | ```java 17 | /** 18 | * Created by gzdaijie on 16/6/5 19 | * 动态规划,对于n个数, 左边可能有0 -> n-1个数,右边对应有n-1 -> 0个数 20 | * 公式 f(n) = Σ f(i) * f(n - i - 1), i(0...n-1) 21 | */ 22 | public class Solution { 23 | public int numTrees(int n) { 24 | int[] dp = new int[n + 1]; 25 | dp[0] = 1; 26 | for (int i = 1; i <= n; i++) { 27 | for (int j = 0; j < i; j++) { 28 | dp[i] += dp[j] * dp[i - j - 1]; 29 | } 30 | } 31 | return dp[n]; 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /source/leetcode/61.Rotate List.md: -------------------------------------------------------------------------------- 1 | ### [Rotate List](https://leetcode.com/problems/rotate-list/) 2 | 3 | > Given a list, rotate the list to the right by k places, where k is non-negative.
4 | > For example:
5 | > Given 1->2->3->4->5->NULL and k = 2,
6 | > return 4->5->1->2->3->NULL. 7 | 8 | 题目大意:给定一个链表,右移k个位置 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | import java.util.*; 14 | /** 15 | * Created by gzdaijie on 16/5/26 16 | */ 17 | public class Solution { 18 | public ListNode rotateRight(ListNode head, int k) { 19 | ListNode p = head, pre = null, last= null; 20 | int len = 0; 21 | while (p != null) { 22 | len++; 23 | last = p; 24 | p = p.next; 25 | } 26 | if (len == 0) return head; 27 | // 将链表分为 len - k,和k 2个部分 28 | k = len - k % len; 29 | p = head; 30 | while (k-- > 0) { 31 | pre = p; 32 | p = p.next; 33 | } 34 | 35 | if (p != null && last != null) { 36 | last.next = head; 37 | pre.next = null; 38 | 39 | } 40 | return p == null ? head : p; 41 | } 42 | } 43 | ``` -------------------------------------------------------------------------------- /source/leetcode/109.Convert Sorted List to Binary Search Tree.md: -------------------------------------------------------------------------------- 1 | ### [Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) 2 | 3 | > Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. 4 | 5 | 题目大意:给定一个有序链表,将其转化成平衡二叉搜索树 6 | 7 | 题目难度:Medium 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/6/8 12 | * slow每次走一步,fast每次走2步,那么fast走完,slow恰好走到中点 13 | * pre记录slow的前一个节点,pre.next = null,可以拆分链表 14 | */ 15 | public class Solution { 16 | public TreeNode sortedListToBST(ListNode head) { 17 | if (head == null) return null; 18 | 19 | ListNode pre = null, slow = head, fast = head; 20 | while (fast != null && fast.next != null) { 21 | pre = slow; 22 | slow = slow.next; 23 | fast = fast.next.next; 24 | } 25 | 26 | TreeNode node = new TreeNode(slow.val); 27 | 28 | if (pre == null) return node; 29 | pre.next = null; 30 | node.left = sortedListToBST(head); 31 | node.right = sortedListToBST(slow.next); 32 | return node; 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /source/leetcode/112.Path Sum.md: -------------------------------------------------------------------------------- 1 | ### [Path Sum](https://leetcode.com/problems/path-sum/) 2 | 3 | > Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the
values along the path equals the given sum. 4 | > For example:
5 | > Given the below binary tree and sum = 22,
6 | > 5
7 | > / \
8 | > 4 8
9 | > / / \
10 | > 11 13 4
11 | > / \ \
12 | > 7 2 1
13 | > return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22. 14 | 15 | 题目大意:给定二叉树,判断是否存在根-叶路径,使得该路径上的值的和等于目标值 16 | 17 | 题目难度:Easy 18 | 19 | ```java 20 | /** 21 | * Created by gzdaijie on 16/6/9 22 | */ 23 | public class Solution { 24 | public boolean hasPathSum(TreeNode root, int sum) { 25 | if (root == null) return false; 26 | if (root.left == null && root.right == null) return sum == root.val; 27 | if (root.left != null && hasPathSum(root.left, sum - root.val)) return true; 28 | return root.right != null && hasPathSum(root.right, sum - root.val); 29 | } 30 | } 31 | ``` -------------------------------------------------------------------------------- /source/leetcode/21.Merge Two Sorted Lists.md: -------------------------------------------------------------------------------- 1 | ### [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) 2 | 3 | > Merge two sorted linked lists and return it as a new list.
4 | > The new list should be made by splicing together the nodes of the first two lists. 5 | 6 | 题目大意:合并2个有序链表为一个新的链表,返回新链表头指针,要求不能新创建链表,合并只能在原链表上执行 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/8 13 | * 将最后的结果存在l1中 14 | * l1.val < l2.val 则l1继续前行 15 | * 否则将l2的当前节点插入l1当前节点之前 16 | */ 17 | public class Solution { 18 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 19 | ListNode head; 20 | ListNode p = new ListNode(0); 21 | p.next = l1; 22 | head = p; 23 | 24 | while (l1 != null && l2 != null) { 25 | if (l1.val < l2.val) { 26 | p = p.next; 27 | l1 = l1.next; 28 | } else { 29 | p = p.next = l2; 30 | l2 = l2.next; 31 | p.next = l1; 32 | } 33 | } 34 | if (l2 != null) { 35 | p.next = l2; 36 | } 37 | return head.next; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/48.Rotate Image.md: -------------------------------------------------------------------------------- 1 | ### [Rotate Image](https://leetcode.com/problems/rotate-image/) 2 | 3 | > You are given an n x n 2D matrix representing an image.
4 | > Rotate the image by 90 degrees (clockwise).
5 | > Follow up: Could you do this in-place? 6 | 7 | 题目大意:顺时针旋转方阵,要求空间复杂度为O(1) 8 | 9 | 题目难度:Medium 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/23 14 | * 先转置,再左右交换即可 15 | */ 16 | public class Solution { 17 | public void rotate(int[][] matrix) { 18 | if (matrix == null || matrix.length == 0) return; 19 | 20 | int len = matrix.length; 21 | for (int i = 0; i < len; i++) { 22 | for (int j = i + 1; j < len; j++) { 23 | swap(matrix, i, j, j, i); 24 | } 25 | } 26 | 27 | for (int i = 0; i < len; i++) { 28 | for (int j = 0; j < len/2; j++) { 29 | swap(matrix, i, j, i, len - j - 1); 30 | } 31 | } 32 | } 33 | 34 | private void swap(int[][] matrix, int x1, int y1, int x2, int y2) { 35 | int tmp = matrix[x1][y1]; 36 | matrix[x1][y1] = matrix[x2][y2]; 37 | matrix[x2][y2] = tmp; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/55.Jump Game.md: -------------------------------------------------------------------------------- 1 | ### [Jump Game](https://leetcode.com/problems/jump-game/) 2 | 3 | > Given an array of non-negative integers, you are initially positioned at the first index of the array.
4 | > Each element in the array represents your maximum jump length at that position.
5 | > Determine if you are able to reach the last index.
6 | > For example:
7 | > * A = [2,3,1,1,4], return true.
8 | > * A = [3,2,1,0,4], return false. 9 | 10 | 题目大意:给定一个数组,数组的每个值代表从当前位置可以走到的最长步数,判断是否可以到达终点 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | /** 16 | * Created by gzdaijie on 16/5/26 17 | * step记录可以走到的地方,step > len - 1说明可以走到终点 18 | */ 19 | public class Solution { 20 | public boolean canJump(int[] nums) { 21 | if (nums.length == 1) return true; 22 | 23 | int len = nums.length; 24 | int step = 0; 25 | 26 | for (int i = 0; i < len - 1; i++) { 27 | if (i > step) return false; // i超过step,说明无法到达step 28 | if (i + nums[i] > step) step = Math.max(i + nums[i], step); // 更新可以走到的最远位置 29 | if (step >= len - 1) return true; // 超过len - 1,说明可以到达终点 30 | } 31 | return false; 32 | } 33 | } 34 | ``` -------------------------------------------------------------------------------- /source/leetcode/35.Search Insert Position.md: -------------------------------------------------------------------------------- 1 | ### [Search Insert Position](https://leetcode.com/problems/search-insert-position/) 2 | 3 | > Given a sorted array and a target value, return the index if the target is found.
4 | > If not, return the index where it > would be if it were inserted in order.
5 | > You may assume no duplicates in the array.
6 | > Here are few examples.
7 | > * [1,3,5,6], 5 → 2
8 | > * [1,3,5,6], 2 → 1
9 | > * [1,3,5,6], 7 → 4
10 | > * [1,3,5,6], 0 → 0 11 | 12 | 题目大意:给定排好序的数组和目标值,返回目标值的索引,若不存在,返回可以插入的位置 13 | 14 | 题目难度:Medium 15 | 16 | ```java 17 | /** 18 | * Created by gzdaijie on 16/5/20 19 | */ 20 | public class Solution { 21 | public int searchInsert(int[] nums, int target) { 22 | int len = nums.length; 23 | int left = 0, right = nums.length - 1; 24 | while (left <= right) { 25 | int mid = (left + right) / 2; 26 | if (nums[mid] == target) return mid; 27 | 28 | if (nums[mid] > target) { 29 | right = mid - 1; 30 | } else { 31 | left = mid + 1; 32 | } 33 | } 34 | return left; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /source/leetcode/67. Add Binary.md: -------------------------------------------------------------------------------- 1 | ### [Add Binary](https://leetcode.com/problems/add-binary/) 2 | 3 | > Given two binary strings, return their sum (also a binary string).
4 | > For example,a = "11",b = "1"
5 | > Return "100". 6 | 7 | 题目大意:实现二进制加法,字符串表示 8 | 9 | 题目难度:Easy 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/28 14 | */ 15 | public class Solution { 16 | public String addBinary(String a, String b) { 17 | int len1 = a.length(); 18 | int len2 = b.length(); 19 | if (len1 == 0) return b; 20 | if (len2 == 0) return a; 21 | 22 | StringBuilder result = new StringBuilder(); 23 | Boolean flag = false; 24 | char ch1, ch2; 25 | int tmp; 26 | while (len1 > 0 || len2 >0) { 27 | --len1; 28 | --len2; 29 | ch1 = len1 >= 0 ? a.charAt(len1) : '0'; 30 | ch2 = len2 >= 0 ? b.charAt(len2) : '0'; 31 | tmp = ch1 + ch2 - '0' * 2 + (flag ? 1 : 0); 32 | result.append((char)((tmp % 2) + '0')); 33 | flag = tmp/2 > 0; 34 | } 35 | if (flag) result.append('1'); 36 | return String.valueOf(result.reverse()); 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /source/leetcode/62.Unique Paths.md: -------------------------------------------------------------------------------- 1 | ### [Unique Paths](https://leetcode.com/problems/unique-paths/) 2 | 3 | > A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
4 | > The robot can only move either down or right at any point in time.
5 | > The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
6 | > How many possible unique paths are there? 7 | 8 | 题目大意:给定一个m*n的矩阵,一只机器人想从左上角走到右下角,每次只能向下向右走一格,问有多少种走法。 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/26 15 | * 动态规划,map[i][j] = map[i - 1][j] + [i][j - 1] 16 | * 复杂度 O(M * N) 17 | */ 18 | public class Solution { 19 | public int uniquePaths(int m, int n) { 20 | if (m < 1 || n < 1) return 0; 21 | 22 | int[][] map = new int[m][n]; 23 | 24 | for (int i = 0; i < m; i++) map[i][0] = 1; 25 | for (int i = 0; i < n; i++) map[0][i] = 1; 26 | 27 | 28 | for (int i = 1; i < m; i++) { 29 | for (int j = 1; j < n; j++) { 30 | map[i][j] = map[i - 1][j] + map[i][j - 1]; 31 | } 32 | } 33 | return map[m - 1][n - 1]; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /source/leetcode/26.Remove Duplicates from Sorted Array.md: -------------------------------------------------------------------------------- 1 | ### [Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) 2 | 3 | > Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.
4 | > Do not allocate extra space for another array, you must do this in place with constant memory.
5 | > Given input array nums = [1,1,2],
6 | > Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
7 | > It doesn't matter what you leave beyond the new length. 8 | 9 | 题目大意:给定已排序数组,移除其中的重复元素,返回新数组长度,要求移除操作在原数组上进行,空间复杂度O(1),数组可以有残留数字 10 | 11 | 题目难度:Easy 12 | 13 | ```java 14 | /** 15 | * Created by gzdaijie on 16/5/8 16 | * 相邻2个数比较,不相同时,计数,新的数覆盖重复的数 17 | */ 18 | public class Solution { 19 | public int removeDuplicates(int[] nums) { 20 | if (nums == null || nums.length == 0) return 0; 21 | 22 | int len = nums.length; 23 | int k = 1; 24 | for (int i = 0; i < len - 1; i++) { 25 | if (nums[i] != nums[i + 1]) { 26 | nums[k++] = nums[i + 1]; 27 | } 28 | } 29 | return k; 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /source/leetcode/19.Remove Nth Node From End of List.md: -------------------------------------------------------------------------------- 1 | ### [Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/) 2 | 3 | > Given a linked list, remove the nth node from the end of list and return its head.
4 | > For example,
5 | > Given linked list: 1->2->3->4->5, and n = 2.
6 | > After removing the second node from the end, the linked list becomes 1->2->3->5. 7 | 8 | 题目大意:删除链表的倒数第n个节点,返回头指针,给定n是有效的,要求只能遍历一遍链表 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/5 15 | * 2个指针,一快一慢,快的提前走n步,走完n步后,两个一起走,直到快的走到终点 16 | * 这时,慢的指针的下一个节点,就是待删除的节点 17 | */ 18 | public class Solution { 19 | public ListNode removeNthFromEnd(ListNode head, int n) { 20 | ListNode headNode = new ListNode(0); 21 | ListNode slow = headNode; 22 | ListNode fast = headNode; 23 | headNode.next = head; 24 | 25 | while (fast.next != null) { 26 | fast = fast.next; 27 | if (n <= 0) { 28 | slow = slow.next; 29 | } 30 | --n; 31 | } 32 | if (slow.next != null) { 33 | slow.next = slow.next.next; 34 | } 35 | return headNode.next; 36 | } 37 | } 38 | ``` -------------------------------------------------------------------------------- /source/leetcode/64.Minimum Path Sum.md: -------------------------------------------------------------------------------- 1 | ### [Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) 2 | 3 | > Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
4 | > Note: You can only move either down or right at any point in time. 5 | 6 | 题目大意:给定一个矩阵,从左上角走到右下角,找到数字和最小的路径,返回该和,只能向下向右走 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/28 13 | * 动态规划 14 | */ 15 | public class Solution { 16 | public int minPathSum(int[][] grid) { 17 | if (grid.length == 0 || grid[0].length == 0) return 0; 18 | 19 | int m = grid.length; 20 | int n = grid[0].length; 21 | int[][] result = new int[m][n]; 22 | 23 | result[0][0] = grid[0][0]; 24 | for (int i = 1; i < m; i++) result[i][0] = result[i - 1][0] + grid[i][0]; 25 | for (int i = 1; i < n; i++) result[0][i] = result[0][i - 1] + grid[0][i]; 26 | 27 | for (int i = 1; i < m; i++) { 28 | for (int j = 1; j < n; j++) { 29 | result[i][j] = Math.min(result[i - 1][j], result[i][j - 1]) + grid[i][j]; 30 | } 31 | } 32 | return result[m - 1][n - 1]; 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /source/leetcode/106.Construct Binary Tree from Inorder and Postord.md: -------------------------------------------------------------------------------- 1 | 106.Construct Binary Tree from Inorder and Postorder Traversal.md 2 | 3 | > Given inorder and postorder traversal of a tree, construct the binary tree.
4 | > Note: You may assume that duplicates do not exist in the tree. 5 | 6 | 题目大意:根据中序和后序遍历,构造二叉树 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | import java.util.*; 12 | /** 13 | * Created by gzdaijie on 16/6/7 14 | */ 15 | public class Solution { 16 | public TreeNode buildTree(int[] inorder, int[] postorder) { 17 | return buildTreeHelper(inorder, 0, postorder, 0, inorder.length); 18 | } 19 | 20 | private TreeNode buildTreeHelper(int[] inorder, int index1, int[] postorder, int index2, int len) { 21 | if (len == 0) return null; 22 | 23 | int num = postorder[index2 + len - 1]; 24 | int count = 0; 25 | TreeNode root = new TreeNode(num); 26 | 27 | for (int i = 0; i < len; i++) { 28 | if (inorder[index1 + i] == num) break; 29 | count++; 30 | } 31 | root.left = buildTreeHelper(inorder, index1, postorder, index2, count); 32 | root.right = buildTreeHelper(inorder, index1 + count + 1, postorder, index2 + count, len - count - 1); 33 | return root; 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /source/leetcode/77.Combinations.md: -------------------------------------------------------------------------------- 1 | ### [Combinations](https://leetcode.com/problems/combinations/) 2 | 3 | > Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
4 | > For example, If n = 4 and k = 2, a solution is:
5 | > [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4]] 6 | 7 | 题目大意:给定数字n和k,找出所有1->n中可能的k个数组合 8 | 9 | 题目难度:Medium 10 | 11 | ```java 12 | import java.util.*; 13 | 14 | /** 15 | * Created by gzdaijie on 16/6/2 16 | */ 17 | public class Solution { 18 | private int n, k; 19 | private List> result = new ArrayList<>(); 20 | 21 | public List> combine(int n, int k) { 22 | this.n = n; 23 | this.k = k; 24 | ArrayList tmp = new ArrayList<>(); 25 | combineRecursive(0, tmp); 26 | return result; 27 | } 28 | 29 | private void combineRecursive(int count, ArrayList tmp) { 30 | if (count == k) { 31 | result.add((ArrayList)tmp.clone()); 32 | return; 33 | } 34 | 35 | int i = count > 0 ? tmp.get(count - 1) + 1 : 1; 36 | for (; i <= n; i++) { 37 | tmp.add(i); 38 | combineRecursive(count + 1, tmp); 39 | tmp.remove(count); 40 | } 41 | } 42 | } 43 | ``` -------------------------------------------------------------------------------- /source/leetcode/105.Construct Binary Tree from Preorder and Inorder.md: -------------------------------------------------------------------------------- 1 | ### [Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) 2 | 3 | > Given preorder and inorder traversal of a tree, construct the binary tree.
4 | > Note: You may assume that duplicates do not exist in the tree. 5 | 6 | 题目大意:根据树的先序遍历和中序遍历生成二叉树,返回根节点 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/7 13 | * 先序遍历的第一值就是子树的根节点,中序遍历中该值左右两边分别是左子树和右子树 14 | */ 15 | public class Solution { 16 | public TreeNode buildTree(int[] preorder, int[] inorder) { 17 | return helper(preorder, 0, inorder, 0, preorder.length); 18 | } 19 | 20 | private TreeNode helper(int[] preorder, int index1, int[] inorder, int index2, int len) { 21 | if (len == 0) return null; 22 | 23 | int cnt = 0; 24 | for (; cnt < len; cnt++) { 25 | if (inorder[index2 + cnt] == preorder[index1]) break; 26 | } 27 | TreeNode root = new TreeNode(preorder[index1]); 28 | root.left = helper(preorder, index1 + 1, inorder, index2, cnt); 29 | root.right = helper(preorder, index1 + cnt + 1, inorder, index2 + cnt + 1, len - cnt - 1); 30 | return root; 31 | } 32 | } 33 | ``` -------------------------------------------------------------------------------- /source/leetcode/6.ZigZag Conversion.md: -------------------------------------------------------------------------------- 1 | ### [ZigZag Conversion](https://leetcode.com/problems/zigzag-conversion/) 2 | 3 | > The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this
4 | > P A H N
5 | > A P L S I I G
6 | > Y I R 7 | 8 | 题目大意:给定一个字符串,按Z形排列,按行输出排列结果,convert("PAYPALISHIRING", 3) => "PAHNAPLSIIGYIR",Z形列数是可变的。 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/4 15 | * 找规律的题目,当然也可以构造二维字符串 16 | * 周期是2 * numsRows - 1, 同一周期内,第j列下一个数为i + (numsRows * 2 - j) 17 | */ 18 | public class Solution { 19 | public String convert(String s, int numRows) { 20 | if (numRows == 1 || s == null) return s; 21 | 22 | String result = ""; // 换做字符数组会更快一些 23 | int len = s.length(); 24 | int step = 2 * numRows - 2; 25 | for (int j = 1; j <= numRows ; j++) { 26 | for (int i = j; i <= len; i += step) { 27 | result += s.charAt(i - 1); 28 | if (j != 1 && j != numRows) { 29 | int t = (numRows - j) * 2 + i; 30 | if (t <= len) { 31 | result += s.charAt(t - 1); 32 | } 33 | } 34 | } 35 | } 36 | return result; 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /source/leetcode/125.Valid Palindrome.md: -------------------------------------------------------------------------------- 1 | ### [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) 2 | 3 | > Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
4 | > For example,
5 | > * "A man, a plan, a canal: Panama" is a palindrome.
6 | > * "race a car" is not a palindrome. 7 | 8 | 题目大意:判断给定字符串是不是回文,忽略非数字密码,大小写不敏感 9 | 10 | 题目难度:Easy 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/6/12 15 | */ 16 | public class Solution { 17 | public boolean isPalindrome(String s) { 18 | char[] str = s.toCharArray(); 19 | int left = 0; 20 | int right = str.length - 1; 21 | 22 | while (left < right) { 23 | if (!Character.isAlphabetic(str[left]) && !Character.isDigit(str[left])) { 24 | left++; 25 | continue; 26 | } 27 | if (!Character.isAlphabetic(str[right]) && !Character.isDigit(str[right])) { 28 | right--; 29 | continue; 30 | } 31 | if (Character.toLowerCase(str[left]) != Character.toLowerCase(str[right])) { 32 | return false; 33 | } 34 | left++; 35 | right--; 36 | } 37 | return true; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/58.Length of Last Word.md: -------------------------------------------------------------------------------- 1 | ### [Length of Last Word.md](https://leetcode.com/problems/length-of-last-word/) 2 | 3 | > Given a string s consists of upper/lower-case alphabets and empty space characters ' ',
4 | > return the length of last word in the string.
5 | > If the last word does not exist, return 0.
6 | > Note: A word is defined as a character sequence consists of non-space characters only.
7 | > For example, Given s = "Hello World", return 5. 8 | 9 | 题目大意:求给定字符串的中最后一个不含空格字符串的长度,如果没有返回0 10 | 11 | 题目难度:Easy 12 | 13 | ```java 14 | /** 15 | * Created by gzdaijie on 16/5/14 16 | * String.split(regex, limit) 方法,可用特定正则表达式分割字符串 17 | * 空间复杂度O(N) 18 | */ 19 | public class Solution { 20 | public int lengthOfLastWord(String s) { 21 | if (s == null || s.length() == 0) return 0; 22 | 23 | String[] strings = s.split(" "); 24 | return strings.length > 0 ? strings[strings.length - 1].length() : 0; 25 | } 26 | } 27 | ``` 28 | 29 | ```java 30 | /** 31 | * Created by gzdaijie on 16/5/14 32 | * 空间复杂度O(1),时间复杂度O(K) 33 | */ 34 | public class Solution { 35 | public int lengthOfLastWord(String s) { 36 | if (s == null || s.trim().length() == 0) return 0; 37 | s = s.trim(); 38 | return s.length() - s.lastIndexOf(' ') - 1; 39 | } 40 | } 41 | ``` -------------------------------------------------------------------------------- /source/leetcode/114.Flatten Binary Tree to Linked List.md: -------------------------------------------------------------------------------- 1 | ### [Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) 2 | 3 | > Given a binary tree, flatten it to a linked list in-place.
4 | > For example,
5 | > Given
6 | > 1
7 | > / \
8 | > 2 5
9 | > / \ \
10 | > 3 4 6
11 | > The flattened tree should look like:
12 | > 1
13 | > \
14 | > 2
15 | > \
16 | > 3
17 | > \
18 | > 4
19 | > \
20 | > 5
21 | > \
22 | > 6 23 | 24 | 题目大意:展平二叉树 25 | 26 | 题目难度:Medium 27 | 28 | ```java 29 | /** 30 | * Created by gzdaijie on 16/6/9 31 | */ 32 | public class Solution { 33 | public void flatten(TreeNode root) { 34 | if (root == null) return; 35 | 36 | flatten(root.left); 37 | flatten(root.right); 38 | 39 | if (root.left != null) { 40 | TreeNode tmp = root.right; 41 | TreeNode tail = root.left; 42 | while (tail.right != null) tail = tail.right; 43 | root.right = root.left; 44 | tail.right = tmp; 45 | root.left = null; 46 | } 47 | } 48 | } 49 | ``` -------------------------------------------------------------------------------- /source/leetcode/34.Search for a Range.md: -------------------------------------------------------------------------------- 1 | ### [Search for a Range.md](https://leetcode.com/problems/search-for-a-range/) 2 | 3 | > Given a sorted array of integers, find the starting and ending position of a given target value.
4 | > Your algorithm's runtime complexity must be in the order of O(log n).
5 | > If the target is not found in the array, return [-1, -1].
6 | > * For example,
7 | > * Given [5, 7, 7, 8, 8, 10] and target value 8,
8 | > * return [3, 4]. 9 | 10 | 题目大意:给定一个升序的数组和一个目标值,返回目标值在数组中的最先出现和最后出现的位置,空间O(1),时间O(N) 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | /** 16 | * Created by gzdaijie on 16/5/20 17 | */ 18 | public class Solution { 19 | public int[] searchRange(int[] nums, int target) { 20 | int[] result = {-1, -1}; 21 | if(nums == null || nums.length == 0) return result; 22 | 23 | int left = 0, right = nums.length - 1; 24 | 25 | while (left < right) { 26 | int mid = (left + right) / 2; 27 | if (nums[mid] < target) left = mid + 1; 28 | else right = mid; 29 | } 30 | 31 | if (nums[left] != target) return result; 32 | 33 | result[0] = left; 34 | 35 | while (++left <= nums.length - 1 && nums[left] == target); /* empty */ 36 | result[1] = left - 1; 37 | return result; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/41.First Missing Positive.md: -------------------------------------------------------------------------------- 1 | [First Missing Positive](https://leetcode.com/problems/first-missing-positive/) 2 | 3 | > Given an unsorted integer array, find the first missing positive integer.
4 | > For example,
5 | > * Given [1,2,0] return 3,
6 | > * and [3,4,-1,1] return 2.
7 | > Your algorithm should run in O(n) time and uses constant space. 8 | 9 | 题目大意:给定一个未排序的数组,找到第一个缺少的正数数,要求时间O(N),空间O(1) 10 | 11 | 题目难度:Hard 12 | 13 | ```java 14 | /** 15 | * Created by gzdaijie on 16/5/21 16 | * 首先可以确定,丢失的正数不超过 length,那可以在数组上标记某个数是否丢失了 17 | * 第一次遍历,删除小于等于0 或大于等于length的数 18 | * 第二次遍历,将num[num[i] - 1]加2n,即nums[2] > n表示2出现过了,因为加上n后,可以仍可取余判断代表哪个正数 19 | * 第三次遍历,找到第一个小于2len的位置 k, 则证明k+1没有出现过 20 | */ 21 | public class Solution { 22 | public int firstMissingPositive(int[] nums) { 23 | if (nums == null || nums.length == 0) return 1; 24 | 25 | int len = nums.length; 26 | for (int i = 0; i < len; i++) { 27 | if (nums[i] < 0 || nums[i] > len) nums[i] = 0; 28 | } 29 | 30 | for (int i = 0; i < len; i++) { 31 | if (nums[i] > 0) { 32 | nums[(nums[i] - 1) % len] += 2 * len; 33 | } 34 | } 35 | 36 | int k = -1; 37 | while (++k < len && nums[k] > len); /* empty */ 38 | return k + 1; 39 | } 40 | } 41 | ``` -------------------------------------------------------------------------------- /source/leetcode/129.Sum Root to Leaf Numbers.md: -------------------------------------------------------------------------------- 1 | ### [Sum Root to Leaf Numbers](https://leetcode.com/problems/sum-root-to-leaf-numbers/) 2 | 3 | > Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
4 | > An example is the root-to-leaf path 1->2->3 which represents the number 123.
5 | > Find the total sum of all root-to-leaf numbers.
6 | > For example,
7 | > 1
8 | > / \
9 | > 2 3
10 | > The root-to-leaf path 1->2 represents the number 12.
11 | > The root-to-leaf path 1->3 represents the number 13.
12 | > Return the sum = 12 + 13 = 25. 13 | 14 | 题目大意:给定二叉树,根->叶的路径组成了一个数,返回所有数的和 15 | 16 | 题目难度:Medium 17 | 18 | ```java 19 | /** 20 | * Created by gzdaijie on 16/6/13 21 | */ 22 | public class Solution { 23 | public int sumNumbers(TreeNode root) { 24 | if (root == null) return 0; 25 | return helper(root, root.val); 26 | } 27 | 28 | private int helper(TreeNode root, int sum) { 29 | if (root.left == null && root.right == null) return sum; 30 | 31 | int left = 0, right = 0; 32 | if (root.left != null) left = helper(root.left, sum * 10 + root.left.val); 33 | if (root.right != null) right = helper(root.right, sum * 10 + root.right.val); 34 | return left + right; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /source/leetcode/73.Set Matrix Zeroes.md: -------------------------------------------------------------------------------- 1 | ### [Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) 2 | 3 | > Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. 4 | 5 | 题目大意:给定一个矩阵,将0所在的行和列的所有元素智0,要求就地替换 6 | 7 | 题目难度:Medium 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/5/30 12 | * 复杂度O(N * M) 13 | */ 14 | public class Solution { 15 | public void setZeroes(int[][] matrix) { 16 | if (matrix == null || matrix.length == 0) return; 17 | if (matrix[0].length == 0) return; 18 | 19 | int m = matrix.length; 20 | int n = matrix[0].length; 21 | // flag[0...m-1]标记行, flag[m...m + n - 1]标记列 22 | boolean[] flag = new boolean[m + n]; 23 | 24 | for (int i = 0; i < m; i++) { 25 | for (int j = 0; j < n; j++) { 26 | if (matrix[i][j] != 0) continue; 27 | flag[i] = flag[m + j] = true; 28 | } 29 | } 30 | // 行置为0 31 | for (int i = 0; i < m; i++) { 32 | if (!flag[i]) continue; 33 | for (int j = 0; j < n; j++) matrix[i][j] = 0; 34 | } 35 | // 列置为0 36 | for (int i = 0; i < n; i++) { 37 | if (!flag[m + i]) continue; 38 | for (int j = 0; j < m; j++) matrix[j][i] = 0; 39 | } 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /source/leetcode/36.Valid Sudoku.md: -------------------------------------------------------------------------------- 1 | ### [Valid Sudoku](https://leetcode.com/problems/valid-sudoku/) 2 | 3 | > Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
4 | > The Sudoku board could be partially filled, where empty cells are filled with the character '.'. 5 | 6 | 题目大意:给定一个数独,判断该数独是否可用,未填数字的地方,用'.'代替 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/8 13 | * 每次遇到数字board[i][j],将第i行,第j列,第i/3*3 + j/3块的这个数字标记为出现过 14 | * 一旦矛盾,说明数独不可解 15 | */ 16 | public class Solution { 17 | public boolean isValidSudoku(char[][] board) { 18 | Boolean[][] row = new Boolean[9][9]; 19 | Boolean[][] col = new Boolean[9][9]; 20 | Boolean[][] block = new Boolean[9][9]; 21 | 22 | for (int i = 0; i < 9; i++) { 23 | for (int j = 0; j < 9; j++) { 24 | if (board[i][j] != '.') { 25 | int t = board[i][j] - '1'; 26 | // 初始值为null,并不是false 27 | if (row[i][t] == null && col[j][t] == null && block[i/3 * 3 + j/3][t] == null) { 28 | row[i][t] = col[j][t] = block[i/3 * 3 + j/3][t] = true; 29 | } else { 30 | return false; 31 | } 32 | } 33 | } 34 | } 35 | return true; 36 | } 37 | } 38 | ``` -------------------------------------------------------------------------------- /source/leetcode/120.Triangle.md: -------------------------------------------------------------------------------- 1 | ### [Triangle](https://leetcode.com/problems/triangle/) 2 | 3 | > Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
4 | >
5 | > For example, given the following triangle
6 | > [ [2],
7 | > [3,4],
8 | > [6,5,7],
9 | > [4,1,8,3]]
10 | > The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
11 | > Note:
12 | > Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle. 13 | 14 | 题目大意:给定一个上述的三角形,寻找从顶到底和最小的路径,要求空间复杂度O(N) 15 | 16 | 题目难度:Medium 17 | 18 | ```java 19 | import java.util.*; 20 | 21 | /** 22 | * Created by gzdaijie on 16/6/11 23 | * 动态规划, i 从 len -> 0 24 | * fun(k) = min(fun(k), fun(k + 1)) + matrix[i][k] 25 | */ 26 | public class Solution { 27 | public int minimumTotal(List> triangle) { 28 | int len = triangle.size(); 29 | int[] result = new int[len + 1]; 30 | 31 | for (int i = len - 1; i >= 0; i--) { 32 | List row = triangle.get(i); 33 | for (int j = 0; j <= i; j++) { 34 | result[j] = Math.min(result[j], result[j + 1]) + row.get(j); 35 | } 36 | } 37 | return result[0]; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/80.Remove Duplicates from Sorted Array II.md: -------------------------------------------------------------------------------- 1 | ### [Remove Duplicates from Sorted Array II](https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/) 2 | 3 | > Follow up for "Remove Duplicates":
4 | > What if duplicates are allowed at most twice?
5 | > For example,
6 | > Given sorted array nums = [1,1,1,2,2,3],
7 | > Your function should return length = 5,
8 | > with the first five elements of nums being 1, 1, 2, 2 and 3.
9 | > It doesn't matter what you leave beyond the new length. 10 | 11 | 题目大意:给定一个已经排好序的数组,去重,每个数字至多出现2次,返回去重后数组的长度,去重在原数组上进行。 12 | 13 | 题目难度:Medium 14 | 15 | ```java 16 | /** 17 | * Created by gzdaijie on 16/6/4 18 | * 使用isDup记录是否新加的数已经出现过 19 | * 空间复杂度O(1),时间复杂度O(N) 20 | */ 21 | public class Solution { 22 | public int removeDuplicates(int[] nums) { 23 | if (nums.length < 3) return nums.length; 24 | 25 | int k = 0; 26 | int last = nums[0]; 27 | boolean isDup = false; 28 | for (int i = 1; i < nums.length; i++) { 29 | if (nums[i] != last) { 30 | nums[++k] = last = nums[i]; 31 | isDup = false; 32 | continue; 33 | } 34 | if (isDup) continue; 35 | nums[++k] = last; 36 | isDup = true; 37 | } 38 | return k + 1; 39 | } 40 | } 41 | ``` -------------------------------------------------------------------------------- /source/leetcode/118.Pascal's Triangle.md: -------------------------------------------------------------------------------- 1 | ### [Pascal's Triangle](https://leetcode.com/problems/pascals-triangle/) 2 | 3 | > Given numRows, generate the first numRows of Pascal's triangle.
4 | > For example, given numRows = 5,
5 | > Return
6 | > [ [1],
7 | > [1,1],
8 | > [1,2,1],
9 | > [1,3,3,1],
10 | > [1,4,6,4,1]]
11 | 12 | 题目大意:根据给定列数输出杨辉三角 13 | 14 | 题目难度:Medium 15 | 16 | ```java 17 | import java.util.*; 18 | 19 | /** 20 | * Created by gzdaijie on 16/6/9 21 | */ 22 | public class Solution { 23 | public List> generate(int numRows) { 24 | List> result = new ArrayList<>(); 25 | if (numRows <= 0) return result; 26 | 27 | List first = new ArrayList<>(); 28 | first.add(1); 29 | result.add(first); 30 | 31 | if (numRows == 1) return result; 32 | 33 | for (int i = 0; i < numRows - 1; i++) { 34 | List pre = result.get(i); 35 | int size = pre.size(); 36 | List item = new ArrayList<>(); 37 | 38 | item.add(1); 39 | for (int j = 0; j < size - 1; j++) { 40 | item.add(pre.get(j) + pre.get(j + 1)); 41 | } 42 | item.add(1); 43 | result.add(item); 44 | } 45 | return result; 46 | } 47 | } 48 | ``` -------------------------------------------------------------------------------- /source/leetcode/74.Search a 2D Matrix.md: -------------------------------------------------------------------------------- 1 | ### [Search a 2D Matrix](https://leetcode.com/problems/search-a-2d-matrix/) 2 | 3 | > Write an efficient algorithm that searches for a value in an m x n matrix.
4 | > This matrix has the following properties:
5 | > Integers in each row are sorted from left to right.
6 | > The first integer of each row is greater than the last integer of the previous row.
7 | > For example,
8 | > Consider the following matrix:
9 | > [[1, 3, 5, 7],
10 | > [10, 11, 16, 20],
11 | > [23, 30, 34, 50]]
12 | > Given target = 3, return true. 13 | 14 | 题目大意:给定一个递增矩阵(没一行从左到右递增,下一行第一个数大于上一行最后一个数,判断一个数是否存在于矩阵中) 15 | 16 | 题目难度:Medium 17 | 18 | ```java 19 | /** 20 | * Created by gzdaijie on 16/5/30 21 | * 先找到最大的x,如果target存在,target必然在Row x中 22 | * 然后再找到Col y 23 | * 时间复杂度O(M + N),空间复杂度O(1) 24 | */ 25 | public class Solution { 26 | public boolean searchMatrix(int[][] matrix, int target) { 27 | if (matrix == null || matrix.length == 0) return false; 28 | if (matrix[0].length == 0) return false; 29 | 30 | int m = matrix.length; 31 | int n = matrix[0].length; 32 | int x = 0, y = 0; 33 | 34 | while (x < m - 1 && matrix[x + 1][y] <= target) x++; 35 | while (y < n - 1 && matrix[x][y + 1] <= target) y++; 36 | 37 | return matrix[x][y] == target; 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /source/leetcode/98.Validate Binary Search Tree.md: -------------------------------------------------------------------------------- 1 | ### [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/) 2 | 3 | > Given a binary tree, determine if it is a valid binary search tree (BST).
4 | > Assume a BST is defined as follows:
5 | > * The left subtree of a node contains only nodes with keys less than the node's key.
* 6 | > * The right subtree of a node contains only nodes with keys greater than the node's key.
* 7 | > * Both the left and right subtrees must also be binary search trees.
8 | 9 | 题目大意:判断给定的树是不是二叉搜索树 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | import java.util.Stack; 15 | /** 16 | * Created by gzdaijie on 16/6/5 17 | * 对于二叉搜索树,中序遍历的结果是递增的 18 | */ 19 | public class Solution { 20 | public boolean isValidBST(TreeNode root) { 21 | long pre = Integer.MIN_VALUE; 22 | Stack stack = new Stack<>(); 23 | 24 | pre = pre - 1; 25 | while (true) { 26 | while (root != null) { 27 | stack.push(root); 28 | root = root.left; 29 | } 30 | if (stack.isEmpty()) break; 31 | TreeNode tmp = stack.pop(); 32 | 33 | if (tmp.val <= pre) return false; 34 | if (tmp.right != null) root = tmp.right; 35 | 36 | pre = tmp.val; 37 | } 38 | return true; 39 | } 40 | } 41 | ``` -------------------------------------------------------------------------------- /source/leetcode/11.Container With Most Water.md: -------------------------------------------------------------------------------- 1 | ### [Container With Most Water](https://leetcode.com/problems/container-with-most-water/) 2 | 3 | > Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai).
4 | > n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0).
5 | > Find two lines, which together with x-axis forms a container, such that the container contains the most water. 6 | 7 | 题目大意:给定一个大小为n的数组,这个数组代表点 (i,ai),连接(i,ai)和(i,0),形成了n条垂直于x轴的线段,每2条线段和x轴围成一个水桶,问哪一个水桶装的水最多。返回装水量 8 | 9 | 题目难度:Medium 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/11 14 | * 水桶短板效应, 装水量等于宽度*2个条线段较小值, 15 | * left = 0, right = length - 1,计算面积和短板, 短板在左边则右移,否则左移 16 | * 时间复杂度O(n) 17 | */ 18 | public class Solution { 19 | public int maxArea(int[] height) { 20 | if (height == null || height.length < 2) return 0; 21 | 22 | int left = 0; 23 | int right = height.length - 1; 24 | int shorter, result = 0; 25 | while (left < right) { 26 | shorter = Math.min(height[left], height[right]); 27 | result = Math.max(result, (right - left) * shorter); 28 | if (shorter == height[left]) { 29 | ++left; 30 | } else { 31 | --right; 32 | } 33 | } 34 | return result; 35 | } 36 | } 37 | ``` -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Leetcode java 算法题", 3 | "description": "Leetcode java 算法题", 4 | "language": "zh-hans", 5 | "links": { 6 | "sidebar": { 7 | "geektutu的主页": "https://geektutu.com/series", 8 | "Leetcode Java算法练习": "https://github.com/gzdaijie/leetcode-java" 9 | } 10 | }, 11 | "plugins": [ 12 | "-highlight", 13 | "expandable-chapters", 14 | "splitter", 15 | "page-footer-ex", 16 | "prism", 17 | "github", 18 | "github-buttons", 19 | "sitemap-general" 20 | ], 21 | "pluginsConfig": { 22 | "sitemap-general": { 23 | "prefix": "https://gzdaijie.github.io/leetcode-java/" 24 | }, 25 | "expandable-chapters": {}, 26 | "page-footer-ex": { 27 | "copyright": "[gzdaijie](https://github.com/gzdaijie)", 28 | "markdown": true, 29 | "update_label": "updated", 30 | "update_format": "YYYY-MM-DD HH:mm:ss" 31 | }, 32 | "github": { 33 | "url": "https://github.com/gzdaijie/leetcode-java" 34 | }, 35 | "github-buttons": { 36 | "buttons": [{ 37 | "user": "gzdaijie", 38 | "repo": "leetcode-java", 39 | "type": "star", 40 | "size": "large" 41 | }] 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /source/leetcode/78.Subsets.md: -------------------------------------------------------------------------------- 1 | ### [Subsets](https://leetcode.com/problems/subsets/) 2 | 3 | > Given a set of distinct integers, nums, return all possible subsets.
4 | > Note:
5 | > * Elements in a subset must be in non-descending order.
6 | > * The solution set must not contain duplicate subsets.
7 | > For example, If nums = [1,2,3], a solution is:
8 | > [ [3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]] 9 | 10 | 题目大意:返回给定数组的所有子集,每个子集内元素非降序排列,不允许重复 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | import java.util.*; 16 | 17 | /** 18 | * Created by gzdaijie on 16/6/3 19 | * 数组的子集共有2^n个 20 | * 事实上,0 -> 2^n-1的二进制数就是子集的一种表示方式 21 | * 二进制的第k位为0,表示子集不含第k个元素,为1则含 22 | */ 23 | public class Solution { 24 | public List> subsets(int[] nums) { 25 | List> result = new ArrayList<>(); 26 | result.add(new ArrayList()); 27 | if (nums == null || nums.length == 0) return result; 28 | 29 | int len = nums.length; 30 | long count = 1 << len; 31 | 32 | Arrays.sort(nums); 33 | for (int i = 1; i < count; i++) { 34 | long t = i; 35 | List item = new ArrayList<>(); 36 | for (int j = 0; j < len; j++ , t = t >> 1) { 37 | if ((t & 1) == 1) item.add(nums[j]); 38 | } 39 | result.add(item); 40 | } 41 | return result; 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /source/leetcode/3.Longest Substring Without Repeating Characters.md: -------------------------------------------------------------------------------- 1 | ### [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) 2 | 3 | > Given a string, find the length of the longest substring without repeating characters.
4 | > Given "pwwkew", the answer is "wke" 5 | 6 | 题目大意:找出给定字符串最长无重复字符的子串长度。例如"pwwkew", "wke",答案是3 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/3 13 | * 遍历字符串,使用数组chars记录当前子串中某个字符ch出现的位置,默认为 -1 14 | * start记录当前子串的起点位置 15 | * 如果字符没有出现过,char[ch]记录位置,计算长度更新max 16 | * 如果出现过, 则将start->重复字符的这一段字符串的字符位置还原为 -1, 更新start 17 | * 返回 max 18 | */ 19 | 20 | public class Solution { 21 | public int lengthOfLongestSubstring(String s) { 22 | int[] chars = new int[256]; 23 | for (int i = 0; i < 256; ++i) { 24 | chars[i] = -1; 25 | } 26 | 27 | int start, max; 28 | start = max = 0; 29 | for (int i = 0; i < s.length(); ++i) { 30 | char ch = s.charAt(i); 31 | if (chars[ch] == -1) { 32 | chars[ch] = i; 33 | max = Math.max(max, i - start + 1); 34 | } else { 35 | while (start < chars[ch] + 1) { 36 | chars[s.charAt(start++)] = -1; 37 | } 38 | chars[ch] = i; 39 | } 40 | } 41 | return max; 42 | 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /source/leetcode/82.Remove Duplicates from Sorted List II.md: -------------------------------------------------------------------------------- 1 | ### [Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/) 2 | 3 | > Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
4 | > For example,
5 | > Given 1->2->3->3->4->4->5, return 1->2->5.
6 | > Given 1->1->1->2->3, return 2->3. 7 | 8 | 题目大意:删除给定链表中所有重复过的元素,只留下没有重复过的元素,例如 1->2-2,返回 1 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/11 15 | * 思路:A->B->C->D,A为确认不重复的节点,value = B.value,比较C及之后节点val == value ? 16 | * 相等则移除,若不相等,更新 A,以及value 17 | * 空间复杂度 O(1) 18 | */ 19 | public class Solution { 20 | public ListNode deleteDuplicates(ListNode head) { 21 | if (head == null || head.next == null) return head; 22 | 23 | ListNode h = new ListNode(0); 24 | ListNode p; 25 | h.next = head; 26 | head = h; 27 | 28 | while (h != null && h.next != null) { 29 | int value = h.next.val; 30 | int count = 1; 31 | p = h.next.next; 32 | 33 | while (p!= null && p.val == value) { 34 | p = p.next; 35 | ++count; 36 | } 37 | if (count > 1) { 38 | h.next = p; 39 | } else { 40 | h = h.next; 41 | } 42 | } 43 | return head.next; 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /source/leetcode/13.Roman to Integer.md: -------------------------------------------------------------------------------- 1 | ### [Roman to Integer](https://leetcode.com/problems/roman-to-integer/) 2 | 3 | > Given a roman numeral, convert it to an integer.
4 | > Input is guaranteed to be within the range from 1 to 3999. 5 | 6 | 题目大意:将一个1-3999范围内的罗马数字转为整数 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/8 13 | * I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000) 14 | * 左>右,左+右; 左<右,右-左 15 | * MCMXCVI => 1000 + 100 + 1000 + 10 + 100 - 20 + 5 + 1 16 | */ 17 | public class Solution { 18 | public int romanToInt(String s) { 19 | if (s == null || s.length() == 0) return 0; 20 | int[] valueMap = new int[26]; 21 | 22 | valueMap['I' - 'A'] = 1; 23 | valueMap['V' - 'A'] = 5; 24 | valueMap['X' - 'A'] = 10; 25 | valueMap['L' - 'A'] = 50; 26 | valueMap['C' - 'A'] = 100; 27 | valueMap['D' - 'A'] = 500; 28 | valueMap['M' - 'A'] = 1000; 29 | 30 | int len = s.length(); 31 | int last = s.charAt(0) - 'A'; 32 | int result = valueMap[last]; 33 | for (int i = 1; i < len; i++) { 34 | int ch = s.charAt(i) - 'A'; 35 | result += valueMap[ch]; 36 | if (valueMap[ch] > valueMap[last]) { 37 | result -= valueMap[last] * 2; 38 | } 39 | last = ch; 40 | } 41 | return result; 42 | } 43 | } 44 | ``` 45 | 46 | > 参考:[维基百科——罗马数字](https://zh.wikipedia.org/wiki/%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97) -------------------------------------------------------------------------------- /source/leetcode/92.Reverse Linked List II.md: -------------------------------------------------------------------------------- 1 | ### [Reverse Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) 2 | 3 | > Reverse a linked list from position m to n. Do it in-place and in one-pass.
4 | > For example:
5 | > Given 1->2->3->4->5->NULL, m = 2 and n = 4,
6 | > return 1->4->3->2->5->NULL.
7 | > Note:
8 | > Given m, n satisfy the following condition:
9 | > 1 ≤ m ≤ n ≤ length of list. 10 | 11 | 题目大意:给定链表,翻转m->n之间的元素,空间复杂度O(1),链表只可以遍历一次 12 | 13 | 题目难度:Medium 14 | 15 | ```java 16 | /** 17 | * Created by gzdaijie on 16/6/5 18 | * 找到m-1(p)和m(q),采用头插法将m + 1 -> n之间的数插到q之间 19 | * 更新q和cnt, head始终指向第m个元素,head.next即等待头插的元素 20 | * 避免m == 1,为链表添加头h 21 | */ 22 | public class Solution { 23 | public ListNode reverseBetween(ListNode head, int m, int n) { 24 | if (head == null || head.next == null || m == n) return head; 25 | ListNode h = new ListNode(-1); 26 | ListNode p, q; 27 | int cnt = 1; 28 | 29 | q = h.next = head; 30 | p = h; 31 | // 找到第m和m-1个元素 32 | while (cnt < m) { 33 | p = head; 34 | q = head = head.next; 35 | cnt++; 36 | } 37 | // 将m+1->n元素依次头插到p,q之间 38 | while (cnt < n) { 39 | ListNode t = head.next; 40 | head.next = head.next.next; 41 | t.next = q; 42 | q = p.next = t; 43 | cnt++; 44 | } 45 | return h.next; 46 | } 47 | } 48 | ``` -------------------------------------------------------------------------------- /source/leetcode/102.Binary Tree Level Order Traversal.md: -------------------------------------------------------------------------------- 1 | ### [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) 2 | 3 | > Given a binary tree, return the level order traversal of its nodes' values.
4 | > (ie, from left to right, level by level).
5 | > For example:
6 | > Given binary tree [3,9,20,null,null,15,7],
7 | > 3
8 | > / \
9 | > 9 20
10 | > / \
11 | > 15 7
12 | > return its level order traversal as:
13 | > [[3], [9,20], [15,7]] 14 | 15 | 题目大意:层次遍历给定二叉树 16 | 17 | 题目难度:Easy 18 | 19 | ```java 20 | import java.util.*; 21 | /** 22 | * Created by gzdaijie on 16/6/7 23 | */ 24 | public class Solution { 25 | public List> levelOrder(TreeNode root) { 26 | Queue queue = new LinkedList<>(); 27 | List> result = new ArrayList<>(); 28 | if (root == null) return result; 29 | 30 | queue.offer(root); 31 | while (true) { 32 | List item = new ArrayList<>(); 33 | int size = queue.size(); 34 | if (size == 0) return result; 35 | while (size-- > 0) { 36 | TreeNode tmp = queue.poll(); 37 | item.add(tmp.val); 38 | if (tmp.left != null) queue.offer(tmp.left); 39 | if (tmp.right != null) queue.offer(tmp.right); 40 | } 41 | result.add(item); 42 | } 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /source/leetcode/23.Merge k Sorted Lists.md: -------------------------------------------------------------------------------- 1 | ### [Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) 2 | 3 | > Merge k sorted linked lists and return it as one sorted list.
4 | > Analyze and describe its complexity. 5 | 6 | 题目大意:合并k个排序好的链表,分析复杂度 7 | 8 | 题目难度:Hard 9 | 10 | 11 | ```java 12 | import java.util.*; 13 | 14 | /** 15 | * Created by gzdaijie on 16/5/9 16 | * 优先队列,相当于最小堆,每次取出最小值,如果有后续节点,入队 17 | * 复杂度O(N*K*log(K)) => N个数,维护K大小的优先队列(因为每次出队,至多入队一个) 18 | */ 19 | public class Solution { 20 | public ListNode mergeKLists(ListNode[] lists) { 21 | if (lists == null || lists.length == 0) return null; 22 | 23 | Queue queue = new PriorityQueue(10, new Comparator() { 24 | @Override 25 | public int compare(ListNode o1, ListNode o2) { 26 | if (o1.val > o2.val) return 1; 27 | if (o1.val < o2.val) return -1; 28 | return 0; 29 | } 30 | }); 31 | 32 | for (int i = 0; i < lists.length; i++) { 33 | if (lists[i] != null) queue.add(lists[i]); 34 | } 35 | 36 | ListNode head = new ListNode(0); 37 | ListNode p = head; 38 | while (!queue.isEmpty()) { 39 | p.next = queue.poll(); 40 | p = p.next; 41 | if (p.next != null) { 42 | queue.add(p.next); 43 | } 44 | p.next = null; 45 | } 46 | return head.next; 47 | } 48 | } 49 | ``` -------------------------------------------------------------------------------- /source/leetcode/1.Two Sum.md: -------------------------------------------------------------------------------- 1 | ### [Two Sum](https://leetcode.com/problems/two-sum/) 2 | 3 | > Given an array of integers, return indices of the two numbers such that they add up to a specific target.
4 | > You may assume that each input would have exactly one solution. 5 | 6 | 题目大意:给定一个数组,和一个目标值,找出数组中相加恰好等于目标值的2个数的下标,结果只有1个 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | import java.util.Arrays; 12 | /** 13 | * Created by gzdaijie on 16/5/1. 14 | * 从大到小排序,首先将首尾相加,首尾指针start,end初始化为0, len-1 15 | * 如果和小于目标值,++start,大于目标值,--end 16 | * 复杂度 O(NlgN) 17 | */ 18 | public class Solution { 19 | public int[] twoSum(int[] nums, int target) { 20 | int len = nums.length; 21 | int start = 0, end = len - 1; 22 | int[] origin_nums = (int[])nums.clone(); 23 | Arrays.sort(nums); 24 | while (start < end) { 25 | int t = nums[start] + nums[end]; 26 | if(t < target){ 27 | ++start; 28 | } else if(t > target) { 29 | --end; 30 | } else { 31 | break; 32 | } 33 | } 34 | 35 | start = nums[start]; 36 | end = nums[end]; 37 | 38 | int[] result = new int[2]; 39 | int index = 0; 40 | for (int i = 0; i < len; i++) { 41 | if(origin_nums[i] == start || origin_nums[i] == end) { 42 | result[index++] = i; 43 | if (index == 2)break; 44 | } 45 | } 46 | return result; 47 | } 48 | } 49 | 50 | ``` -------------------------------------------------------------------------------- /source/leetcode/86.Partition List.md: -------------------------------------------------------------------------------- 1 | ### [Partition List](https://leetcode.com/problems/partition-list/) 2 | 3 | > Given a linked list and a value x,
4 | > partition it such that all nodes less than x come before nodes greater than or equal to x.
5 | > You should preserve the original relative order of the nodes in each of the two partitions.
6 | > For example,
7 | > Given 1->4->3->2->5->2 and x = 3,
8 | > return 1->2->2->4->3->5. 9 | 10 | 题目大意:给定一个链表,和目标值x,将比x小的数字放在链表的左边,大于等于x的数字放在链表的右边,要求不能改变数字在原来链表中的相对顺序 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | /** 16 | * Created by gzdaijie on 16/6/4 17 | * left_h 记录左边的头, right_h 记录右边的头 18 | * left左边的尾,right右边的尾,最后连接起来即可 19 | * 时间复杂度O(N),空间复杂度O(1) 20 | */ 21 | public class Solution { 22 | public ListNode partition(ListNode head, int x) { 23 | ListNode left_h, right_h, left, right; 24 | left_h = left = right = right_h = null; 25 | 26 | while (head != null) { 27 | if (head.val < x) { 28 | if (left_h == null) left_h = left = head; 29 | else left = left.next = head; 30 | } else { 31 | if (right_h == null) right_h = right = head; 32 | else right = right.next = head; 33 | } 34 | head = head.next; 35 | } 36 | 37 | if (left_h == null) return right_h; 38 | 39 | if (right_h != null) { 40 | right.next = null; 41 | left.next = right_h; 42 | } 43 | return left_h; 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /source/leetcode/122.Best Time to Buy and Sell Stock II.md: -------------------------------------------------------------------------------- 1 | ### [Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) 2 | 3 | > Say you have an array for which the ith element is the price of a given stock on day i.
4 | > Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). 5 | 6 | 题目大意:给定一个数组,代表股票每天的价格,假设可以买卖多次,但必须每次买入之前需要卖出。问最大利润。 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/6/11 13 | * 发现价格下跌,就将之前买的全部卖掉, 14 | * 并准备买入低价格的股票 15 | * min 表示准备买入的价格, max 表示准备卖出的价格 16 | */ 17 | public class Solution { 18 | public int maxProfit(int[] prices) { 19 | if (prices == null || prices.length < 2) return 0; 20 | 21 | int len = prices.length; 22 | int min = prices[0]; 23 | int max = prices[0]; 24 | int result = 0; 25 | 26 | for (int i = 1; i < len; i++) { 27 | if (prices[i] < prices[i - 1]) { 28 | result += max - min; 29 | max = min = prices[i]; 30 | continue; 31 | } 32 | if (prices[i] < min) { 33 | min = Math.min(min, prices[i]); 34 | } else { 35 | max = Math.max(max, prices[i]); 36 | } 37 | } 38 | return result + max - min; 39 | 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /source/leetcode/89.Gray Code.md: -------------------------------------------------------------------------------- 1 | ### [Gray Code](https://leetcode.com/problems/gray-code/) 2 | 3 | > The gray code is a binary numeral system where two successive values differ in only one bit.
4 | > Given a non-negative integer n representing the total number of bits in the code,
5 | > print the sequence of gray code. A gray code sequence must begin with 0.
6 | > For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
7 | > * 00 - 0
8 | > * 01 - 1
9 | > * 11 - 3
10 | > * 10 - 2 11 | 12 | 题目大意:给定数字n,代表n个比特,返回格雷码序列,即相邻的两个数只相差一个比特 13 | 14 | 题目难度:Medium 15 | 16 | 17 | ```java 18 | import java.util.*; 19 | /** 20 | * Created by gzdaijie on 16/6/4 21 | * 思路,0 => [0] 22 | * 1 => 0 << 1 + 0, 0 << 1 + 1 => [0, 1] 23 | * 2 => 0 << 1 + 0, 0 << 1 + 1, 1 << 1 + 1 , 1 << 1 + 0 = > [0,1,3,2] 24 | * 即每次在上一次的结果后面依次添加0,1,1,0,0,1,1.... 25 | * 时间复杂度O(2^0 + 2^1 + 2^2 + ... + 2^n ) = O(2^N) 26 | */ 27 | public class Solution { 28 | public List grayCode(int n) { 29 | Queue result = new LinkedList<>(); 30 | 31 | result.add(0); 32 | for (int i = 0; i < n; i++) { 33 | int tag = 0; 34 | int size = result.size(); 35 | while (size-- > 0) { 36 | int top = result.poll(); 37 | result.add((top << 1) + tag); // 这里tag与上一循环的tag相同 38 | tag ^= 1; // tag 0变1,或1变0 39 | result.add((top << 1) + tag); 40 | } 41 | } 42 | return (List)result; 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /source/leetcode/63.Unique Paths II.md: -------------------------------------------------------------------------------- 1 | ### [Unique Paths II](https://leetcode.com/problems/unique-paths-ii/) 2 | 3 | > Follow up for "Unique Paths":
4 | > Now consider if some obstacles are added to the grids. How many unique paths would there be?
5 | > An obstacle and empty space is marked as 1 and 0 respectively in the grid.
6 | > For example,
7 | > There is one obstacle in the middle of a 3x3 grid as illustrated below.
8 | > [[0,0,0],
9 | > [0,1,0],
10 | > [0,0,0]]
11 | > The total number of unique paths is 2.
12 | > Note: m and n will be at most 100. 13 | 14 | 题目大意:给定一个矩阵,0代表可以走,1代表障碍物不可走,求出从左上角到右下角的所有可能路径数量 15 | 16 | 题目难度:Medium 17 | 18 | /** 19 | * Created by gzdaijie on 16/5/27 20 | * 到达阻碍物的路径为0 21 | * 在第0行,和第0列,到达障碍物及障碍物之后的节点路径也为0 22 | */ 23 | public class Solution { 24 | public int uniquePathsWithObstacles(int[][] obstacleGrid) { 25 | int m = obstacleGrid.length; 26 | if (m < 1) return 0; 27 | int n = obstacleGrid[0].length; 28 | if (n < 1) return 0; 29 | 30 | int[][] result = new int[m][n]; 31 | 32 | for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) result[i][0] = 1; 33 | 34 | for (int i = 0; i < n && obstacleGrid[0][i] == 0; i++) result[0][i] = 1; 35 | 36 | for (int i = 1; i < m; i++) { 37 | for (int j = 1; j < n; j++) { 38 | result[i][j] = obstacleGrid[i][j] == 0 ? result[i - 1][j] + result[i][j - 1] : 0; 39 | } 40 | } 41 | 42 | return result[m - 1][n - 1]; 43 | } 44 | } -------------------------------------------------------------------------------- /source/leetcode/60.Permutation Sequence.md: -------------------------------------------------------------------------------- 1 | ### [Permutation Sequence](https://leetcode.com/problems/permutation-sequence/) 2 | 3 | > The set [1,2,3,…,n] contains a total of n! unique permutations.
4 | > By listing and labeling all of the permutations in order,
5 | > We get the following sequence (ie, for n = 3):
6 | > "123", "132", "213", "231", "312", "321"
7 | > Given n and k, return the kth permutation sequence.
8 | > Note: Given n will be between 1 and 9 inclusive. 9 | 10 | 题目大意:给定整数n和k,数字1-n,有n!个全排列,返回第k个 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | import java.util.*; 16 | /** 17 | * Created by gzdaijie on 16/5/26 18 | */ 19 | public class Solution { 20 | public String getPermutation(int n, int k) { 21 | int total = 1; 22 | List pool = new ArrayList<>(); 23 | StringBuilder result = new StringBuilder(); 24 | 25 | for (int i = 1; i <=n; i++) { 26 | total *= i; 27 | pool.add(i); 28 | } 29 | 30 | find(pool, result, total, k); 31 | return result.toString(); 32 | } 33 | 34 | private void find(List pool, StringBuilder result, int total, int k) { 35 | int n = pool.size(); 36 | if (n == 1) { 37 | result.append(pool.get(0)); 38 | return; 39 | } 40 | // (k * n - 1)/total 可以计算出应该是多少打头,加入result后递归 41 | int index = (k * n - 1) / total; 42 | int t = pool.remove(index); 43 | result.append(t); 44 | find(pool, result, total/n, k - total/n * index); 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /source/leetcode/107.Binary Tree Level Order Traversal II.md: -------------------------------------------------------------------------------- 1 | ### [Binary Tree Level Order Traversal II](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/) 2 | 3 | > Given a binary tree, return the bottom-up level order traversal of its nodes' values.
4 | > (ie, from left to right, level by level from leaf to root).
5 | > For example:
6 | > Given binary tree [3,9,20,null,null,15,7],
7 | > 3
8 | > / \
9 | > 9 20
10 | > / \
11 | > 15 7
12 | > return its bottom-up level order traversal as:
13 | > [ [15,7], [9,20], [3] ] 14 | 15 | 题目大意:返回树的层次遍历,每一层从左到右,从叶子层到根 16 | 17 | 题目难度: Medium 18 | 19 | ```java 20 | import java.util.*; 21 | /** 22 | * Created by gzdaijie on 16/6/7 23 | */ 24 | public class Solution { 25 | public List> levelOrderBottom(TreeNode root) { 26 | List> result = new LinkedList<>(); 27 | Queue queue = new LinkedList<>(); 28 | 29 | if (root == null) return result; 30 | queue.add(root); 31 | 32 | while (true) { 33 | int size = queue.size(); 34 | if (size == 0) return result; 35 | 36 | List item = new ArrayList<>(); 37 | while (size-- > 0) { 38 | TreeNode top = queue.poll(); 39 | item.add(top.val); 40 | if (top.left != null) queue.offer(top.left); 41 | if (top.right != null) queue.offer(top.right); 42 | } 43 | result.add(0,item); 44 | } 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /source/leetcode/42.Trapping Rain Water.md: -------------------------------------------------------------------------------- 1 | ### [Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) 2 | 3 | > Given n non-negative integers representing an elevation map where the width of each bar is 1,
4 | > compute how much water it is able to trap after raining.
5 | > For example,
6 | > * Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. 7 | 8 | 题目大意:给定n个整数代表木板的长度(宽度为1),木板水平方向依次放置,求容纳水的体积 9 | 10 | 题目难度:Hard 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/21 15 | * 水桶效应,容量与第二长的木板有关 16 | * 比较首末木板的长度,从较小的木板smaller开始计算sum,直到遇到比smaller大的木板 17 | * 遇到比smaller更大的木板,更新smaller,重复上一个步骤 18 | * 时间O(N), O(1) 19 | * 例如1,0,4,2,5,0,3 20 | * 计算过程 1->0->4(sum=1)-> 3->0->5(sum=4)->4->2->5(sum=6) 21 | */ 22 | public class Solution { 23 | public int trap(int[] height) { 24 | if (height == null || height.length < 2) return 0; 25 | int start = 0 , end = height.length - 1; 26 | int sum = 0; 27 | 28 | while (start <= end) { 29 | if (height[start] < height[end]) { 30 | int smaller = height[start++]; 31 | while (start < end && height[start] <= smaller) { 32 | sum += smaller - height[start]; 33 | start++; 34 | } 35 | } else { 36 | int smaller = height[end--]; 37 | while (start < end && height[end] <= smaller) { 38 | sum += smaller - height[end]; 39 | end--; 40 | } 41 | } 42 | } 43 | return sum; 44 | } 45 | } 46 | ``` -------------------------------------------------------------------------------- /source/leetcode/91.Decode Ways.md: -------------------------------------------------------------------------------- 1 | ### [Decode Ways](https://leetcode.com/problems/decode-ways/) 2 | 3 | > A message containing letters from A-Z is being encoded to numbers using the following mapping:
4 | > 'A' -> 1
5 | > 'B' -> 2
6 | > ...
7 | > 'Z' -> 26
8 | > Given an encoded message containing digits, determine the total number of ways to decode it.
9 | > For example,
10 | > Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12).
11 | > The number of ways decoding "12" is 2. 12 | 13 | 题目大意:A -> Z 分别编码1->26,给定一串编码值,例如"12",可以解码为"AB"和"Z",共2种情况,返回解码方式的个数 14 | 15 | 题目难度:Medium 16 | 17 | ```java 18 | /** 19 | * Created by gzdaijie on 16/6/5 20 | * 0,30,40,50... => 0 21 | * 10,20 => f(n) = f(n-2) 22 | * <=9 || > 26 => f(n) = f(n -1) 23 | * 11 - 26 => f(n) = f(n-1) + f(n - 2) 24 | * 动态规划,时间复杂度O(N), 空间复杂度O(N) 25 | */ 26 | public class Solution { 27 | public int numDecodings(String s) { 28 | int len = s.length(); 29 | if (len == 0 || s.charAt(0) == '0') return 0; 30 | 31 | int[] count = new int[len + 1]; 32 | count[0] = count[1] = 1; 33 | for (int i = 1; i < len; i++) { 34 | int sum = (s.charAt(i - 1) - '0') * 10 + (s.charAt(i) - '0'); 35 | if (sum % 10 == 0) { 36 | if(sum == 10 || sum == 20) count[i + 1] = count[i - 1]; 37 | else return 0; 38 | } 39 | else if (sum < 10 || sum > 26) count[i + 1] = count[i]; 40 | else count[i + 1] = count[i] + count[i - 1]; 41 | } 42 | return count[len]; 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /source/leetcode/47.Permutations II.md: -------------------------------------------------------------------------------- 1 | ### [Permutations II](https://leetcode.com/problems/permutations-ii/) 2 | 3 | > Given a collection of numbers that might contain duplicates, return all possible unique permutations.
4 | > For example,
5 | > * [1,1,2] have the following unique permutations:
6 | > * [1,1,2], [1,2,1], and [2,1,1]. 7 | 8 | 题目大意:给定一个有重复数字的数组,返回全排列 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | import java.util.*; 14 | /** 15 | * Created by gzdaijie on 16/5/22 16 | * 递归解法 17 | * 与46的区别,关键在于去重 18 | * 去重的思想是,先排序,如果nums[1]与nums[2]重复,那么在nums[1]未参与组合前,nums[2]也不参与组合 19 | */ 20 | public class Solution { 21 | public List> permuteUnique(int[] nums) { 22 | List> result = new ArrayList>(); 23 | boolean[] flag = new boolean[nums.length]; 24 | ArrayList tmp = new ArrayList(); 25 | Arrays.sort(nums); 26 | permuteRecursion(result, nums, tmp, flag); 27 | return result; 28 | } 29 | 30 | public void permuteRecursion(List> result, int[] nums, ArrayList tmp, boolean[] flag) { 31 | int len = nums.length; 32 | 33 | if (tmp.size() == len) { 34 | result.add((List) tmp.clone()); 35 | return; 36 | } 37 | 38 | for (int i = 0; i < len; i++) { 39 | if (flag[i] || i > 0 && nums[i] == nums[i -1 ] && !flag[i - 1]) continue; 40 | 41 | flag[i] = true; 42 | tmp.add(nums[i]); 43 | permuteRecursion(result, nums, tmp, flag); 44 | tmp.remove(tmp.size() - 1); 45 | flag[i] = false; 46 | } 47 | } 48 | } 49 | ``` -------------------------------------------------------------------------------- /source/leetcode/113.Path Sum II.md: -------------------------------------------------------------------------------- 1 | ### [Path Sum II](https://leetcode.com/problems/path-sum-ii/) 2 | 3 | > Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.
4 | > For example:
5 | > Given the below binary tree and sum = 22,
6 | > 5
7 | > / \
8 | > 4 8
9 | > / / \
10 | > 11 13 4
11 | > / \ / \
12 | > 7 2 5 1
13 | > return[ [5,4,11,2], [5,8,4,5] ] 14 | 15 | 题目大意:给定一个二叉树和目标值,找出所有和等于目标值的根-叶路径 16 | 17 | 题目难度:Medium 18 | 19 | ```java 20 | import java.util.*; 21 | 22 | /** 23 | * Created by gzdaijie on 16/6/9 24 | */ 25 | public class Solution { 26 | public List> pathSum(TreeNode root, int sum) { 27 | List> result = new ArrayList<>(); 28 | ArrayList tmp = new ArrayList<>(); 29 | if (root != null) helper(result, tmp, root, sum); 30 | return result; 31 | } 32 | 33 | private void helper(List> result, ArrayList item, TreeNode root, int sum) { 34 | item.add(root.val); 35 | 36 | if (root.left == null && root.right == null) { 37 | if (sum == root.val) result.add((List) item.clone()); 38 | return; 39 | } 40 | 41 | if (root.left != null) { 42 | helper(result, item, root.left, sum - root.val); 43 | item.remove(item.size() - 1); 44 | } 45 | 46 | if (root.right != null) { 47 | helper(result, item, root.right, sum - root.val); 48 | item.remove(item.size() - 1); 49 | } 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /source/leetcode/22.Generate Parentheses.md: -------------------------------------------------------------------------------- 1 | ### [Generate Parentheses](https://leetcode.com/problems/generate-parentheses/) 2 | 3 | > Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
4 | > For example, given n = 3, a solution set is:
5 | > "((()))", "(()())", "(())()", "()(())", "()()()" 6 | 7 | 题目大意:给定整数n,返回n对括号所有的合法组合 8 | 9 | 题目难度:Medium 10 | 11 | ```java 12 | import java.util.*; 13 | 14 | /** 15 | * Created by gzdaijie on 16/5/19 16 | * 递归解法,tmp记录构造的字符串 17 | */ 18 | public class Solution { 19 | public List generateParenthesis(int n) { 20 | List result = new ArrayList<>(); 21 | StringBuilder tmp = new StringBuilder(); 22 | recursionGenerate(result, tmp, n, n); 23 | return result; 24 | } 25 | 26 | /** 27 | * 递归构造组合方式 28 | * @param result 记录结果 29 | * @param tmp 记录临时组合的字符串 30 | * @param left 记录左括号剩余个数 31 | * @param right 记录右括号剩余个数 32 | */ 33 | private void recursionGenerate(List result, StringBuilder tmp, int left, int right) { 34 | if (left == 0 && right == 0) { 35 | result.add(tmp.toString()); 36 | return; 37 | } 38 | // 还有剩余的左括号,添加左括号递归 39 | if (left > 0) { 40 | tmp.append('('); 41 | recursionGenerate(result, tmp, left - 1, right); 42 | tmp.setLength(tmp.length() - 1); 43 | } 44 | // 还有剩余的右括号,且剩余的右括号多于左括号,添加右括号递归 45 | if (right > 0 && left < right) { 46 | tmp.append(')'); 47 | recursionGenerate(result, tmp, left, right - 1); 48 | tmp.setLength(tmp.length() - 1); 49 | } 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /source/leetcode/8.String to Integer (atoi).md: -------------------------------------------------------------------------------- 1 | ### [String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/) 2 | 3 | > Implement atoi to convert a string to an integer. 4 | 5 | 题目大意:将一个字符串转换为数组,考虑行首空格,正负号,绝对值大于Integer.MAX_VALUE的,有非数字字符的情况 6 | 7 | 题目难度:Easy 8 | 9 | ```java 10 | /** 11 | * Created by gzdaijie on 16/5/4 12 | * 题目比较简单,关键是注意处理大于int的情况,发现大于int,直接返回最大值即可 13 | */ 14 | public class Solution { 15 | public int myAtoi(String str) { 16 | if (str == null) return 0; 17 | // (1) 去除行首空格 18 | str = this.removeStartSpace(str); 19 | 20 | int i = 0; 21 | int len = str.length(); 22 | long result = 0; 23 | Boolean isNegative = false; 24 | // (2) 判断是否有+-, +-只能出现在第一个字符 25 | if (len == 0) return 0; 26 | if (str.charAt(0) == '+' || str.charAt(0) == '-') { 27 | ++i; 28 | isNegative = str.charAt(0) == '-'; 29 | } 30 | // (3)计算结果途中遇到非数字的字符,结束计算 31 | while (i < len) { 32 | char ch = str.charAt(i); 33 | if (ch < '0' || ch > '9') break; 34 | result = result * 10 + (ch -'0'); 35 | if (result > Integer.MAX_VALUE) { 36 | return isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE; 37 | } 38 | ++i; 39 | } 40 | return isNegative ? (int)result * -1 : (int)result; 41 | } 42 | 43 | private String removeStartSpace(String str) { 44 | int len = str.length(); 45 | for (int i = 0; i < len; i++) { 46 | if (str.charAt(i) != ' ') { 47 | return str.substring(i); 48 | } 49 | } 50 | return ""; 51 | } 52 | } 53 | ``` -------------------------------------------------------------------------------- /source/leetcode/54.Spiral Matrix.md: -------------------------------------------------------------------------------- 1 | ### [Spiral Matrix](https://leetcode.com/problems/spiral-matrix/) 2 | 3 | > Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
4 | > For example,
5 | > Given the following matrix:
6 | > * [[ 1, 2, 3 ],[ 4, 5, 6 ],[ 7, 8, 9 ]]
7 | > * You should return [1,2,3,6,9,8,7,4,5]. 8 | 9 | 题目大意:给定一个m * n的矩阵,按顺时针方向排列 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | import java.util.*; 15 | /** 16 | * Created by gzdaijie on 16/5/25 17 | */ 18 | public class Solution { 19 | public List spiralOrder(int[][] matrix) { 20 | if (matrix == null || matrix.length == 0) return new ArrayList(); 21 | int m = matrix.length; 22 | int n = matrix[0].length; 23 | 24 | int[][] dirs = {{0, 1},{1, 0},{0, -1},{-1, 0}}; 25 | int top = 0, left = 0 ,right = n - 1, bottom = m - 1; 26 | int k = m * n, dir = 0, x = 0, y = 0; 27 | 28 | List result = new ArrayList<>(); 29 | while (k-- > 0) { 30 | result.add(matrix[x][y]); 31 | if (dir == 0 && y >= right) { 32 | top++; 33 | dir = (dir + 1) % 4; 34 | } else if (dir == 1 && x >= bottom) { 35 | right--; 36 | dir = (dir + 1) % 4; 37 | } else if (dir == 2 && y <= left) { 38 | bottom--; 39 | dir = (dir + 1) % 4; 40 | } else if (dir == 3 && x <= top) { 41 | left++; 42 | dir = (dir + 1) % 4; 43 | } 44 | x += dirs[dir][0]; 45 | y += dirs[dir][1]; 46 | } 47 | return result; 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /source/leetcode/49.Group Anagrams.md: -------------------------------------------------------------------------------- 1 | ### [Group Anagrams](https://leetcode.com/problems/anagrams/) 2 | 3 | > Given an array of strings, group anagrams together.
4 | > For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"],
5 | > Return:[ ["ate", "eat","tea"], ["nat","tan"], ["bat"] ]
6 | > Note:
7 | > * For the return value, each inner list's elements must follow the lexicographic order.
8 | > * All inputs will be in lower-case. 9 | 10 | 题目大意:给定一个字符串数组,将其分类,含有相同数量字母的为一类。要求每一类按字母序返回,所有输入为小写 11 | 12 | 题目难度:Medium 13 | 14 | ```java 15 | import java.util.*; 16 | /** 17 | * Created by gzdaijie on 16/5/23 18 | * 不同的质数相乘,结果一定不同,可以用不同质数代替字母 19 | * 判断乘积,即可以判断是否属于同一组,借助hashMap记录键值对 20 | */ 21 | public class Solution { 22 | public static List> groupAnagrams(String[] strs) { 23 | int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103}; 24 | List> result = new ArrayList<>(); 25 | HashMap hash = new HashMap<>(); 26 | 27 | for (String s : strs) { 28 | int key = 1; 29 | for (char ch: s.toCharArray()) { 30 | key *= prime[ch - 'a']; 31 | } 32 | 33 | if (hash.containsKey(key)) { 34 | result.get(hash.get(key)).add(s); 35 | } else { 36 | List t = new ArrayList<>(); 37 | t.add(s); 38 | result.add(t); 39 | hash.put(key, result.size() - 1); 40 | } 41 | } 42 | 43 | for (List list: result) { 44 | Collections.sort(list); 45 | } 46 | return result; 47 | } 48 | } 49 | ``` -------------------------------------------------------------------------------- /source/leetcode/103.Binary Tree Zigzag Level Order Traversal.md: -------------------------------------------------------------------------------- 1 | ### [Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) 2 | 3 | > Given a binary tree, return the zigzag level order traversal of its nodes' values.
4 | > (ie, from left to right, then right to left for the next level and alternate between).
5 | > For example:
6 | > Given binary tree [3,9,20,null,null,15,7],
7 | > 3
8 | > / \
9 | > 9 20
10 | > / \
11 | > 15 7
12 | > return its zigzag level order traversal as:
13 | > [[3], [20,9], [15,7]] 14 | 15 | 题目大意:层次遍历,第一层从左到右,第二层从右到左,依次交换 16 | 17 | 题目难度:Medium 18 | 19 | ```java 20 | import java.util.*; 21 | /** 22 | * Created by gzdaijie on 16/6/7 23 | */ 24 | public class Solution { 25 | public List> zigzagLevelOrder(TreeNode root) { 26 | List> result = new ArrayList<>(); 27 | Queue queue = new LinkedList<>(); 28 | 29 | if (root == null) return result; 30 | queue.add(root); 31 | 32 | boolean tag = true; 33 | while (true) { 34 | int size = queue.size(); 35 | if (size == 0) return result; 36 | 37 | List item = new LinkedList<>(); 38 | while (size-- > 0) { 39 | TreeNode top = queue.poll(); 40 | 41 | if (tag) item.add(top.val); 42 | else item.add(0, top.val); 43 | 44 | if (top.left != null) queue.offer(top.left); 45 | if (top.right != null) queue.offer(top.right); 46 | } 47 | result.add(item); 48 | tag = !tag; 49 | } 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /source/leetcode/93.Restore IP Addresses.md: -------------------------------------------------------------------------------- 1 | ### [Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/) 2 | 3 | > Given a string containing only digits,
4 | > restore it by returning all possible valid IP address combinations.
5 | > For example:
6 | > Given "25525511135",
7 | > return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) 8 | 9 | 题目大意:给定字符串代表无'.'隔开的ip地址,返回所有可能代表的有效的IP地址组合 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | import java.util.*; 15 | /** 16 | * Created by gzdaijie on 16/6/5 17 | * dfs需注意的地方,假定已确定位数k, 待确定 4 - k 18 | * (1) 剩余的长度应小于等于 (4 - k) * 3 19 | * (2) 每位数值需要小于 255 20 | * (3) 每一位除了0外,不能以0开头 21 | */ 22 | public class Solution { 23 | private List result; 24 | 25 | public List restoreIpAddresses(String s) { 26 | result = new ArrayList<>(); 27 | if (s.length() < 4) return result; 28 | 29 | String[] tmp = new String[4]; 30 | ipAddressesDfs(tmp, 0 , s, 0); 31 | return result; 32 | } 33 | 34 | private void ipAddressesDfs(String[] tmp, int index, String s, int k) { 35 | if (index == 4) { 36 | result.add(tmp[0] + "." + tmp[1] + "." + tmp[2] + "." + tmp[3]); 37 | return; 38 | } 39 | 40 | int len = s.length(); 41 | int sum; 42 | for (int j = 1; j <= 3 && k + j <= len; j++) { 43 | // 剩余的字符串长度不能超过 3 * (3 - index), index从0开始 44 | if (len - k - j > 3 * (3 - index)) continue; 45 | 46 | tmp[index] = s.substring(k, k + j); 47 | sum = Integer.parseInt(tmp[index]); 48 | if (sum > 255 ) continue; // 不能大于255 49 | if (j != 1 && tmp[index].charAt(0) == '0') break; // j > 1,不能以0开头 50 | 51 | ipAddressesDfs(tmp, index + 1, s, k + j); 52 | } 53 | } 54 | } 55 | ``` -------------------------------------------------------------------------------- /source/leetcode/16.3Sum Closest.md: -------------------------------------------------------------------------------- 1 | ### [3Sum Closest](https://leetcode.com/problems/3sum-closest/) 2 | 3 | > Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target.
4 | > Return the sum of the three integers.
5 | > You may assume that each input would have exactly one solution.
6 | > * For example, given array S = {-1 2 1 -4}, and target = 1.
7 | > * The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). 8 | 9 | 题目大意:给定数组和一个目标值,数组中有三个数之和与目标值最为接近,返回这三个数的和,值唯一 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | import java.util.Arrays; 15 | 16 | /** 17 | * Created by gzdaijie on 16/5/15 18 | * 复杂度O(N*lgN + N*N) = O(N) 19 | */ 20 | public class Solution { 21 | public int threeSumClosest(int[] nums, int target) { 22 | Arrays.sort(nums); 23 | 24 | int len = nums.length; 25 | int diff = Integer.MAX_VALUE; 26 | int sum, result = 0; 27 | int left, right; 28 | 29 | for (int i = 0; i < len - 2; i++) { 30 | // 避免第一个数重复 31 | if (i != 0) { 32 | while (nums[i - 1] == nums[i] && i < len - 2) ++i; 33 | } 34 | 35 | left = i + 1; 36 | right = len - 1; 37 | while (left < right) { 38 | sum = nums[i] + nums[left] + nums[right]; 39 | if (Math.abs(sum - target) < diff) { 40 | diff = Math.abs(sum - target); 41 | result = sum; 42 | } 43 | if (sum - target > 0) { 44 | --right; 45 | } else if (sum - target < 0) { 46 | ++left; 47 | } else { 48 | return target; 49 | } 50 | } 51 | } 52 | return result; 53 | } 54 | } 55 | ``` -------------------------------------------------------------------------------- /source/leetcode/28.Implement strStr().md: -------------------------------------------------------------------------------- 1 | ### [Implement strStr()](https://leetcode.com/problems/implement-strstr/) 2 | 3 | > Implement strStr().
4 | > Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 5 | 6 | 题目大意:匹配目标字符串,返回位置,若匹配失败,返回-1 7 | 8 | 题目难度:Easy 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/8 13 | * KMP算法 14 | */ 15 | public class Solution { 16 | public int strStr(String haystack, String needle) { 17 | char[] origin = haystack.toCharArray(); 18 | char[] target = needle.toCharArray(); 19 | 20 | int[] next = kmpNext(needle.toCharArray()); 21 | int len1 = origin.length; 22 | int len2 = target.length; 23 | int i = 0; 24 | int j = 0; 25 | while (i < len1 && j < len2) { 26 | if (j == -1 || origin[i] == target[j]) { 27 | ++i; 28 | ++j; 29 | } else { 30 | j = next[j]; 31 | } 32 | } 33 | if (j >= len2) return i - len2; 34 | return -1; 35 | } 36 | 37 | private int[] kmpNext(char[] chars) { 38 | int len = chars.length; 39 | int[] next = new int[len]; 40 | for (int i = 0; i < len ; i++) { 41 | next[i] = -1; 42 | } 43 | 44 | int j = -1; 45 | int i = 0; 46 | while (i < len) { 47 | if (j == -1 || chars[i] == chars[j]) { 48 | ++i; 49 | ++j; 50 | if (i < len) next[i] = j; 51 | } else { 52 | j = next[j]; 53 | } 54 | } 55 | return next; 56 | } 57 | } 58 | ``` 59 | 60 | > 参考1:[KMP算法](http://blog.rainy.im/2016/04/24/string-find/)
61 | > 参考2:[阮一峰——Boyer-Moore算法](http://www.ruanyifeng.com/blog/2013/05/boyer-moore_string_search_algorithm.html) 62 | 63 | 64 | -------------------------------------------------------------------------------- /source/leetcode/94.Binary Tree Inorder Traversal.md: -------------------------------------------------------------------------------- 1 | ### [Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/) 2 | 3 | > Given a binary tree, return the inorder traversal of its nodes' values.
4 | > For example:
5 | > Given binary tree [1,null,2,3],
6 | > 1
7 | > \
8 | > 2
9 | > /
10 | > 3
11 | > return [1,3,2].
12 | > Note: Recursive solution is trivial, could you do it iteratively? 13 | 14 | 题目大意:使用非递归方式完成二叉树的中序遍历 15 | 16 | 题目难度:Medium 17 | 18 | ```java 19 | import java.util.*; 20 | /** 21 | * Created by gzdaijie on 16/6/5 22 | * 递归方式 23 | */ 24 | public class Solution { 25 | public List inorderTraversal(TreeNode root) { 26 | List result = new ArrayList<>(); 27 | midTraversal(root, result); 28 | return result; 29 | } 30 | 31 | private void midTraversal(TreeNode root, List result) { 32 | if (root == null) return; 33 | midTraversal(root.left, result); 34 | result.add(root.val); 35 | midTraversal(root.right, result); 36 | } 37 | } 38 | ``` 39 | 40 | ```java 41 | import java.util.*; 42 | /** 43 | * Created by gzdaijie on 16/6/5 44 | * 非递归方式,一旦左节点不为空,将左节点全部入栈 45 | */ 46 | public class Solution { 47 | public List inorderTraversal(TreeNode root) { 48 | List result = new ArrayList<>(); 49 | midTraversal(root, result); 50 | return result; 51 | } 52 | 53 | private void midTraversal(TreeNode root, List result) { 54 | Stack stack = new Stack<>(); 55 | while (true) { 56 | while (root != null) { 57 | stack.add(root); 58 | root = root.left; 59 | } 60 | if (stack.isEmpty()) break; 61 | TreeNode p = stack.pop(); 62 | result.add(p.val); 63 | root = p.right; 64 | } 65 | } 66 | } 67 | ``` -------------------------------------------------------------------------------- /source/leetcode/39.Combination Sum.md: -------------------------------------------------------------------------------- 1 | ### [Combination Sum](https://leetcode.com/problems/combination-sum/) 2 | 3 | > Given a set of candidate numbers (C) and a target number (T),
4 | > find all unique combinations in C where the candidate numbers sums to T.
5 | > The same repeated number may be chosen from C unlimited number of times.
6 | > Note:
7 | > * All numbers (including target) will be positive integers.
8 | > * Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
9 | > * The solution set must not contain duplicate combinations.
10 | > * For example, given candidate set 2,3,6,7 and target 7,
11 | > * A solution set is: [7],[2, 2, 3] 12 | 13 | 题目大意:给定几个全为正数的集合和一个目标值,找到所有和等于目标值的数的组合,数可以重复,结果以递增序列返回,不能重复 14 | 15 | 题目难度:Medium 16 | 17 | 18 | 19 | ```java 20 | import java.util.*; 21 | 22 | /** 23 | * Created by gzdaijie on 16/5/21 24 | * DFS 25 | */ 26 | public class Solution { 27 | public List> combinationSum(int[] candidates, int target) { 28 | List> result = new ArrayList>(); 29 | Arrays.sort(candidates); 30 | ArrayList tmp = new ArrayList(); 31 | combination(candidates, target, result,tmp, 0, 0); 32 | return result; 33 | 34 | } 35 | 36 | private void combination(int[] candidates, int target, List> result, ArrayList tmp, int k, int sum) { 37 | if (sum == target) { 38 | result.add((ArrayList) tmp.clone()); 39 | return; 40 | } 41 | int len = candidates.length; 42 | for (int i = k; i < len; i++) { 43 | // 小于目标值时,从i开始继续尝试,因为可以重复 44 | if (sum + candidates[i] <= target) { 45 | tmp.add(candidates[i]); 46 | combination(candidates, target,result, tmp, i, sum + candidates[i]); 47 | tmp.remove(tmp.size() - 1); 48 | } 49 | } 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /source/leetcode/59.Spiral Matrix II.md: -------------------------------------------------------------------------------- 1 | ### [Spiral Matrix II](https://leetcode.com/problems/spiral-matrix-ii/) 2 | 3 | > Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.
4 | > For example, Given n = 3,
5 | > You should return the following matrix:
6 | > [
7 | > [ 1, 2, 3 ],
8 | > [ 8, 9, 4 ],
9 | > [ 7, 6, 5 ]
10 | > ] 11 | 12 | 题目大意:顺时针构造一个n维方阵,元素从1-n*n 13 | 14 | 题目难度:Medium 15 | 16 | ```java 17 | /** 18 | * Created by gzdaijie on 16/5/26 19 | */ 20 | public class Solution { 21 | public int[][] generateMatrix(int n) { 22 | int[][] result = new int[n][n]; 23 | 24 | int dir = 0; 25 | int k = 0; 26 | int x = 0, y = 0; 27 | int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 28 | while (k++ < n * n) { 29 | result[x][y] = k; 30 | switch (dir) { 31 | case 0: 32 | if (y < n - 1 && result[x][y + 1] == 0) y++; 33 | else { 34 | dir = (dir + 1) % 4; 35 | x++; 36 | } 37 | break; 38 | case 1: 39 | if (x < n - 1 && result[x + 1][y] == 0) x++; 40 | else { 41 | dir = (dir + 1) % 4; 42 | y--; 43 | } 44 | break; 45 | case 2: 46 | if (y > 0 && result[x][y - 1] == 0) y--; 47 | else { 48 | dir = (dir + 1) % 4; 49 | x--; 50 | } 51 | break; 52 | case 3: 53 | if (x > 0 && result[x - 1][y] == 0) x--; 54 | else { 55 | dir = (dir + 1) % 4; 56 | y++; 57 | } 58 | break; 59 | } 60 | } 61 | return result; 62 | } 63 | } 64 | ``` -------------------------------------------------------------------------------- /source/leetcode/116.Populating Next Right Pointers in Each Node.md: -------------------------------------------------------------------------------- 1 | ### [Populating Next Right Pointers in Each Node](https://leetcode.com/problems/populating-next-right-pointers-in-each-node/) 2 | 3 | > Given a binary tree
4 | > struct TreeLinkNode {
5 | > TreeLinkNode *left;
6 | > TreeLinkNode *right;
7 | > TreeLinkNode *next;
8 | > }
9 | > Populate each next pointer to point to its next right node.
10 | > If there is no next right node, the next pointer should be set to NULL.
11 | > Initially, all next pointers are set to NULL.
12 | > Note:
13 | > * You may only use constant extra space.
14 | > * You may assume that it is a perfect binary tree (ie, all leaves are at the same level,
15 | > * and every parent has two children).
16 | > For example,
17 | > Given the following perfect binary tree,
18 | > 1
19 | > / \
20 | > 2 3
21 | > / \ / \
22 | > 4 5 6 7
23 | > After calling your function, the tree should look like:
24 | > 1 -> NULL
25 | > / \
26 | > 2 -> 3 -> NUL
27 | > / \ / \
28 | > 4->5->6->7 -> NULL 29 | 30 | 题目大意:添加next指针指向二叉树中节点的右边 31 | 32 | 题目难度:Medium 33 | 34 | ```java 35 | import java.util.*; 36 | 37 | /** 38 | * Created by gzdaijie on 16/6/9 39 | */ 40 | public class Solution { 41 | public void connect(TreeLinkNode root) { 42 | Queue queue = new LinkedList<>(); 43 | if (root == null) return; 44 | 45 | queue.offer(root); 46 | while (!queue.isEmpty()) { 47 | int size = queue.size(); 48 | TreeLinkNode pre = null, p; 49 | while (size-- > 0) { 50 | p = queue.poll(); 51 | if (pre != null) pre.next = p; 52 | pre = p; 53 | if (p.left != null) queue.offer(p.left); 54 | if (p.right != null) queue.offer(p.right); 55 | } 56 | } 57 | } 58 | } 59 | ``` -------------------------------------------------------------------------------- /source/leetcode/2.Add Two Numbers.md: -------------------------------------------------------------------------------- 1 | ### [Add Two Numbers](https://leetcode.com/problems/add-two-numbers/) 2 | 3 | > You are given two linked lists representing two non-negative numbers.
4 | > The digits are stored in reverse order and each of their nodes contain a single digit.
5 | > Add the two numbers and return it as a linked list.
6 | > Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
7 | > Output: 7 -> 0 -> 8 8 | 9 | 题目大意:给定2个链表代表2个整数(整数反转之后每一位存在链表的一个节点中,例如2->4->3 代表342),将这两个数相加,以链表形式返回结果 10 | 11 | 题目难度:Mediun 12 | 13 | ```java 14 | import java.math.BigInteger; 15 | 16 | /** 17 | * Created by gzdaijie on 16/5/2 18 | * 思路是依次读取链表中的值,将其还原为一个整数,需要用到BigInteger类 19 | * 最后,2个数相加,将和还原为链表,返回头指针即可 20 | */ 21 | public class Solution { 22 | public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 23 | BigInteger result = new BigInteger("0"); 24 | BigInteger n = new BigInteger("1"); 25 | BigInteger times = new BigInteger("10"); 26 | 27 | // 使用n记录位数,每进一位乘10 28 | while (l1 != null) { 29 | result = result.add(new BigInteger(Integer.toString(l1.val)).multiply(n)); 30 | n = n.multiply(times); 31 | l1 = l1.next; 32 | } 33 | 34 | n = new BigInteger("1"); 35 | while (l2 != null) { 36 | result = result.add(new BigInteger(Integer.toString(l2.val)).multiply(n)); 37 | n = n.multiply(times); 38 | l2 = l2.next; 39 | } 40 | 41 | String s = result.toString(); 42 | int len = s.length(); 43 | char ch = s.charAt(len - 1); 44 | 45 | // head 保存头指针 46 | // tmp 指向尾部,不断新增节点 47 | ListNode head = new ListNode(Character.getNumericValue(ch)); 48 | ListNode tmp = head; 49 | head.next = null; 50 | 51 | for (int i = len - 2; i > -1 ; i--) { 52 | ch = s.charAt(i); 53 | tmp.next = new ListNode(Character.getNumericValue(ch)); 54 | tmp = tmp.next; 55 | tmp.next = null; 56 | } 57 | return head; 58 | } 59 | } 60 | ``` -------------------------------------------------------------------------------- /source/leetcode/43.Multiply Strings.md: -------------------------------------------------------------------------------- 1 | ### [Multiply Strings](https://leetcode.com/problems/multiply-strings/) 2 | 3 | > Given two numbers represented as strings, return multiplication of the numbers as a string.
4 | > Note:
5 | > * The numbers can be arbitrarily large and are non-negative.
6 | > * Converting the input string to integer is NOT allowed.
7 | > * You should NOT use internal library such as BigInteger. 8 | 9 | 题目大意:给定2个数,以字符串形式表示,返回这2个数的乘积,要求不能使用内置高精度函数,给定数字为非负整数 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | /** 15 | * Created by gzdaijie on 16/5/21 16 | * 翻转数字, 观察可知 result[i + j] = nums[i] * num[j] % 10 17 | * 注意处理进位即可 18 | */ 19 | public class Solution { 20 | public String multiply(String num1, String num2) { 21 | char[] str1 = num1.toCharArray(); 22 | char[] str2 = num2.toCharArray(); 23 | char[] result = new char[str1.length + str2.length]; 24 | 25 | for (int i = 0; i < result.length; i++) result[i] = '0'; 26 | 27 | reverse(str1); 28 | reverse(str2); 29 | 30 | int tmp = 0; 31 | for (int i = 0; i < str1.length; i++) { 32 | for (int j = 0; j < str2.length; j++) { 33 | tmp = (str1[i] - '0') * (str2[j] - '0') + (result[i + j] - '0'); 34 | result[i + j] = (char)(tmp % 10 + '0'); 35 | // 将进位预存储在前一位中 36 | result[i + j + 1] += tmp / 10; 37 | } 38 | } 39 | 40 | reverse(result); 41 | 42 | // 去除字符串前所有的 '0' 43 | int count = 0; 44 | for (int i = 0; i < result.length && result[i] == '0'; i++, count++); /* empty */ 45 | 46 | if (count == result.length) return "0"; 47 | return new String(result, count, result.length - count); 48 | } 49 | 50 | private void reverse(char[] chars) { 51 | int len = chars.length; 52 | char ch; 53 | for (int i = 0; i < len/2; i++) { 54 | ch = chars[i]; 55 | chars[i] = chars[len - i - 1]; 56 | chars[len - i - 1] = ch; 57 | } 58 | } 59 | } 60 | ``` -------------------------------------------------------------------------------- /source/leetcode/90.Subsets II.md: -------------------------------------------------------------------------------- 1 | ### [Subsets II](https://leetcode.com/problems/subsets-ii/) 2 | 3 | > Given a collection of integers that might contain duplicates, nums, return all possible subsets.
4 | > Note: The solution set must not contain duplicate subsets.
5 | > For example,
6 | > If nums = [1,2,2], a solution is:
7 | > [ [2],[1],[1,2,2],[2,2],[1,2],[]] 8 | 9 | 题目大意:给定一个包含重复数字的数组,返回其所有的子集 10 | 11 | 题目难度:Medium 12 | 13 | ```java 14 | import java.util.*; 15 | /** 16 | * Created by gzdaijie on 16/6/4 17 | * 对于每一位数字,每个子集可以选择包含或不包含 18 | * 对于重复的数字,特殊处理,即看作是一个整体. 19 | * 例如1,2,2 处理到2时,有三种情况,包含[],包含[2],包含[2,2]共三种情况 20 | */ 21 | public class Solution { 22 | public List> subsetsWithDup(int[] nums) { 23 | Queue> result = new LinkedList<>(); 24 | int[] flag = new int[nums.length]; 25 | 26 | Arrays.sort(nums); 27 | result.add(new ArrayList()); 28 | 29 | /** 30 | * 移除nums中重复的数字,flag记录每个位置数字出现的次数 31 | */ 32 | int k = 0; 33 | for (int i = 0; i < nums.length; i++) { 34 | if (nums[i] == nums[k]) { 35 | flag[k]++; 36 | } else { 37 | flag[++k] = 1; 38 | nums[k] = nums[i]; 39 | } 40 | } 41 | 42 | /** 43 | * 对于k个数,每个子集选择包含或不包含 44 | * 一个数字如果出现了j次,那么就有j+1种包含的可能,分别是[],[x],[x,x],[x...x] 45 | */ 46 | for (int i = 0; i <= k; i++) { 47 | int size = result.size(); 48 | while (size-- > 0) { 49 | List top = result.poll(); 50 | List top_copy; 51 | result.add(top); 52 | for (int j = 0; j < flag[i]; j++) { 53 | top_copy = (List) ((ArrayList) top).clone(); 54 | 55 | for (int l = 0; l <= j; l++) top_copy.add(nums[i]); 56 | result.add(top_copy); 57 | } 58 | } 59 | } 60 | return (List>)result; 61 | } 62 | } 63 | ``` -------------------------------------------------------------------------------- /source/leetcode/40.Combination Sum II.md: -------------------------------------------------------------------------------- 1 | ### [Combination Sum II](https://leetcode.com/problems/combination-sum-ii/) 2 | 3 | > Given a collection of candidate numbers (C) and a target number (T),
4 | > find all unique combinations in C where the candidate numbers sums to T.
5 | > Each number in C may only be used once in the combination.
6 | > Note:
7 | > * All numbers (including target) will be positive integers.
8 | > * Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
9 | > * The solution set must not contain duplicate combinations.
10 | > * For example, given candidate set 10,1,2,7,6,1,5 and target 8,
11 | > * A solution set is: [1, 7],[1, 2, 5] ,[2, 6] ,[1, 1, 6] 12 | 13 | 题目大意:给定一个数组和一个目标值,找出数组中所有和等于目标值的数的组合。要求数组中的数在一个组合中只出现一次,组合中的数以递增形式存储。但是如果数组中某个数出现了多次,组合中的该数也可出现多次,但是次数不超过数组中出现的次数。 14 | 15 | 题目难度:Medium 16 | 17 | 18 | ```java 19 | import java.util.*; 20 | 21 | /** 22 | * Created by gzdaijie on 16/5/21 23 | * DFS 24 | * 与39不同的是,每个数只能用一次,为了避免重复,前缀不允许相同即可 25 | * 前缀不允许相同,即假设数组为1,2,3,4,4,4,前缀为1,2,3,递归时不允许出现多个1,2,3,4 26 | */ 27 | public class Solution { 28 | public List> combinationSum2(int[] candidates, int target) { 29 | List> result = new ArrayList>(); 30 | Arrays.sort(candidates); 31 | 32 | ArrayList tmp = new ArrayList(); 33 | combination(candidates, target, result,tmp, 0); 34 | return result; 35 | } 36 | 37 | private void combination(int[] candidates, int target, List> result, ArrayList tmp, int k) { 38 | if (target == 0) { 39 | result.add((ArrayList) tmp.clone()); 40 | return; 41 | } 42 | int len = candidates.length; 43 | for (int i = k; i < len && candidates[i] <= target; i++) { 44 | if (i != k && candidates[i] == candidates[i - 1]) continue; 45 | tmp.add(candidates[i]); 46 | combination(candidates, target - candidates[i],result, tmp, i + 1); 47 | tmp.remove(tmp.size() - 1); 48 | } 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /source/leetcode/15.3Sum.md: -------------------------------------------------------------------------------- 1 | ### [3Sum](https://leetcode.com/problems/3sum/) 2 | 3 | > Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
4 | > Find all unique triplets in the array which gives the sum of zero.
5 | > Note:
6 | > Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
7 | > The solution set must not contain duplicate triplets.
8 | > For example, given array S = {-1 0 1 2 -1 -4}, A solution set is:
9 | > * (-1, 0, 1) 10 | > * (-1, -1, 2) 11 | 12 | 题目大意:给定无序数组,找出和为0的不重复的三元组,三元组需以升序表示 13 | 14 | 题目难度:Medium 15 | 16 | ```java 17 | import java.util.*; 18 | 19 | /** 20 | * Created by gzdaijie on 16/5/11 21 | * 先排序,后遍历 22 | * 遍历过程中,遇到每个元素,就检测其后面的每2个元素之和与之相加是否为0 23 | * 如何避免重复? 遍历下一个元素时,确保这个元素与上一个元素不同即可 24 | * 例如 -1,-1,-1,1,1,2,第一次是-1, 那么第二次就是 1 25 | * 时间复杂度O(N * lgN + N * N) => O(N * N) 26 | */ 27 | public class Solution { 28 | public List> threeSum(int[] nums) { 29 | List> result = new ArrayList<>(); 30 | Arrays.sort(nums); 31 | 32 | int left, right, sum; 33 | ArrayList triplets; 34 | 35 | for (int i = 0; i < nums.length - 2; i++) { 36 | if (i != 0) { 37 | // 为避免重复,i需要增加到与上次不同 38 | while (nums[i - 1] == nums[i] && i < nums.length - 2) ++i; 39 | } 40 | left = i + 1; 41 | right = nums.length - 1; 42 | 43 | while (left < right) { 44 | sum = nums[i] + nums[left] + nums[right]; 45 | 46 | if (sum == 0) { 47 | triplets = new ArrayList<>(); 48 | triplets.add(nums[i]); 49 | triplets.add(nums[left]); 50 | triplets.add(nums[right]); 51 | result.add(triplets); 52 | ++left; 53 | // 避免后2个数重复,left需增加到与之前不同为止 54 | while (left < right && nums[left - 1] == nums[left]) ++left; 55 | } else if (sum > 0) { 56 | --right; 57 | } else { 58 | ++left; 59 | } 60 | } 61 | } 62 | return result; 63 | } 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /source/leetcode/38.Count and Say.md: -------------------------------------------------------------------------------- 1 | ### [Count and Say](https://leetcode.com/problems/count-and-say/) 2 | 3 | > The count-and-say sequence is the sequence of integers beginning as follows: 4 | > 1, 11, 21, 1211, 111221, ... 5 | > 1 is read off as "one 1" or 11. 6 | > 11 is read off as "two 1s" or 21. 7 | > 21 is read off as "one 2, then one 1" or 1211. 8 | > Given an integer n, generate the nth sequence. 9 | 10 | 题目大意:数字计数并说出来,例如1,读作1个1(11);11读作2个1(21);21->1211->111221->312211 11 | 12 | ```java 13 | /** 14 | * Created by gzdaijie on 16/5/9 15 | * 递归,n为1时是出口 16 | * 在字符串最后添加字符‘#’,是为了统一解决字符计数的问题 17 | */ 18 | public class Solution { 19 | public String countAndSay(int n) { 20 | if (n == 1) return "1"; 21 | 22 | String pre = countAndSay(n - 1) + '#'; 23 | int len = pre.length(); 24 | int count = 1; 25 | char ch = pre.charAt(0); 26 | String result = ""; 27 | for (int i = 1; i < len; i++) { 28 | if (ch == pre.charAt(i)) { 29 | ++count; 30 | } else { 31 | result += (char)(count + '0'); 32 | result += ch; 33 | count = 1; 34 | ch = pre.charAt(i); 35 | } 36 | } 37 | return result; 38 | } 39 | } 40 | ``` 41 | 42 | ```java 43 | /** 44 | * Created by gzdaijie on 16/5/9 45 | * 尾递归改循环,复杂度不变 46 | * 字符串拼接非常耗时,字符串拼接改为数组操作(运行时间 34ms -> 1ms) 47 | */ 48 | public class Solution { 49 | public String countAndSay(int n) { 50 | String result = "1"; 51 | for (int i = 1; i < n; i++) { 52 | result = generateNext(result); 53 | } 54 | return result; 55 | } 56 | private String generateNext(String pre) { 57 | pre = pre + '#'; 58 | int len = pre.length(); 59 | int count = 1; 60 | char ch = pre.charAt(0); 61 | int k = 0; 62 | char[] result = new char[len * 2]; 63 | for (int i = 1; i < len; i++) { 64 | if (ch == pre.charAt(i)) { 65 | ++count; 66 | } else { 67 | result[k++] = (char)(count + '0'); 68 | result[k++] = ch; 69 | count = 1; 70 | ch = pre.charAt(i); 71 | } 72 | } 73 | return String.valueOf(result, 0 ,k); 74 | } 75 | } 76 | ``` -------------------------------------------------------------------------------- /source/leetcode/31.Next Permutation.md: -------------------------------------------------------------------------------- 1 | ### [Next Permutation](https://leetcode.com/problems/next-permutation/) 2 | 3 | > Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
4 | > If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
5 | > The replacement must be in-place, do not allocate extra memory.
6 | > Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
7 | > * 1,2,3 → 1,3,2
8 | > * 3,2,1 → 1,2,3
9 | > * 1,1,5 → 1,5,1 10 | 11 | 题目大意:给定一个数组,代表一个排列,给出该排列的下一个排列(字典序)。要求空间复杂度O(1) 12 | 13 | 题目难度:Medium 14 | 15 | ```java 16 | /** 17 | * Created by gzdaijie on 16/5/18 18 | * 问题的关键是找到使得数字更改最小的节点 19 | * 假设nums长度为n,应当替换的位置为p,可以证明p + 1 -> n降序排列的,且nums[p] < nums[p+1] 20 | * 否则可以找到 q(q>p),使得q + 1->n降序排列,且nums[q] < nums[q+1],替换q,对数字影响更小 21 | * 时间复杂度O(N) 22 | */ 23 | public class Solution { 24 | public void nextPermutation(int[] nums) { 25 | if (nums == null || nums.length == 1) return; 26 | int len = nums.length; 27 | int k = len - 2; 28 | // 找到降序排列的最长后缀 29 | for (; k >=0 && nums[k] >= nums[k + 1] ; k--); /* empty */ 30 | 31 | if (k >= 0) { 32 | // 从后往前,找到恰好比比nums[k]大的数字nums[i],替换nums[k]和nums[i] 33 | for (int i = len - 1; i > k; i--) { 34 | if (nums[i] > nums[k]) { 35 | int t = nums[i]; 36 | nums[i] = nums[k]; 37 | nums[k] = t; 38 | break; 39 | } 40 | } 41 | } 42 | // 翻转k+1 -> len - 1(降序排列的数,翻转之后即可以保证最小) 43 | // 这里有一个特殊情况,k若等于-1,说明整个序列是降序的,那么相当于翻转全部 44 | reverse(nums, k + 1, len - 1); 45 | } 46 | 47 | /** 48 | * 翻转一个数组 49 | * @param nums 待翻转的数组 50 | * @param start 开始位置(含) 51 | * @param end 结束位置(含) 52 | */ 53 | public void reverse(int[] nums, int start, int end) { 54 | int mid = (end - start + 1) / 2; 55 | for (int i = 0; i < mid; i++) { 56 | int t = nums[start + i]; 57 | nums[start + i] = nums[end - i]; 58 | nums[end - i] = t; 59 | } 60 | } 61 | } 62 | ``` 63 | 64 | 参考:[下一个排列图解](https://www.nayuki.io/res/next-lexicographical-permutation-algorithm/next-permutation-algorithm-thumb.png) -------------------------------------------------------------------------------- /source/leetcode/18.4Sum.md: -------------------------------------------------------------------------------- 1 | ### [4Sum](https://leetcode.com/problems/4sum/) 2 | 3 | > Given an array S of n integers, are there elements a, b, c,
4 | > and d in S such that a + b + c + d = target?
5 | > Find all unique quadruplets in the array which gives the sum of target.
6 | > Note:
7 | > Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
8 | > The solution set must not contain duplicate quadruplets.
9 | > * For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
10 | > * A solution set is:
11 | > * (-1, 0, 0, 1)
12 | > * (-2, -1, 1, 2)
13 | > * (-2, 0, 0, 2) 14 | 15 | 题目大意:给定一个数组和4个数,在数组中找出所有和等于这个目标值的4个数,不允许重复,以非递减顺序排列这四个数 16 | 17 | 题目难度:Medium 18 | 19 | ```java 20 | import java.util.*; 21 | 22 | /** 23 | * Created by gzdaijie on 16/5/18 24 | * 类似于15题——3sum, 多加一层循环 25 | * 先以O(N*N)的复杂度枚举可能出现的2个数的组合, 再按照3sum的解法寻找和为target的另外2个数 26 | * 总的时间复杂度O(N*N*N) 27 | */ 28 | public class Solution { 29 | public List> fourSum(int[] nums, int target) { 30 | int len = nums.length; 31 | List> result = new ArrayList>(); 32 | if (len < 4) return result; 33 | 34 | Arrays.sort(nums); 35 | for (int i = 0; i < len - 3; i++) { 36 | if (i != 0) { 37 | while (i < len - 3 && nums[i] == nums[i - 1]) i++; 38 | } 39 | 40 | for (int j = i + 1; j < len - 2; j++) { 41 | if (j != i + 1) { 42 | while (j < len - 2 && nums[j] == nums[j - 1]) j++; 43 | } 44 | 45 | int left = j + 1; 46 | int right = nums.length - 1; 47 | int sum = nums[i] + nums[j]; 48 | while (left < right) { 49 | int total = sum + nums[left] + nums[right]; 50 | if (total == target) { 51 | result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right])); 52 | ++left; 53 | while (left < right && nums[left] == nums[left - 1]) ++left; 54 | } else if (total < target) { 55 | ++left; 56 | } else { 57 | --right; 58 | } 59 | 60 | } 61 | } 62 | } 63 | return result; 64 | } 65 | } 66 | ``` 67 | 68 | > 参考:[15.3Sum](./15.3Sum.md) -------------------------------------------------------------------------------- /tips/String.md: -------------------------------------------------------------------------------- 1 | # Java算法技巧——字符串类 2 | 3 | ## String 4 | 5 | ### 字符串转数字 6 | ```java 7 | String s = "123"; 8 | int value = Integer.parseInt(s); // => 123 9 | value = Integer.valueOf(s) // => 123 10 | ``` 11 | 12 | ### 数字转字符串 13 | ```java 14 | int value = 123; 15 | String s = Integer.toString(value); // => "123" 16 | s = String.valueOf(value); // => "123" 17 | s = "" + value // => "123" 18 | ``` 19 | 20 | ### 字符串,转字符(数组) 21 | ```java 22 | String s = "abc"; 23 | char[] chars = s.toCharArray(); // => ['a','b','c'] 24 | chars[2] == s.charAt(2) // => true 25 | ``` 26 | 27 | ### 字符数组转字符串 28 | ```java 29 | char[] a = {'1', '2', '3', '4'}; 30 | String str = String.valueOf(a); // => "1234" 调用valueOf方法 31 | str = String.valueOf(a, 2 ,2); // => "34",valueOf(data[], offset, count) 32 | str = new String(a); // => "1234" 构造函数转换 33 | ``` 34 | 35 | ### 子串 36 | ```java 37 | String s = "abc" 38 | String sub = s.substring(1, 3); // => "bc" 39 | sub = s.substring(1,2); // => "b",(start,end),start->end-1,不包含end 40 | ``` 41 | 42 | ### 分割 43 | ```java 44 | public String[] split(String regex, int limit) 45 | public String[] split(String regex) 46 | 47 | String s = "ab-bc-cd-de" 48 | String[] str = s.split("-") // => ["ab", "bc", "cd", "de"] 49 | str = s.split("-", 2) // => ["ab","bc-cd-de"], 分割为2段, 50 | str = s.split("-", 1) // => ["ab-bc-cd-de"],1->不分割,0->全分割 51 | ``` 52 | 53 | > 参考:[java split](http://www.tutorialspoint.com/java/java_string_split.htm) 54 | 55 | ### 查找 56 | ```java 57 | // 查找返回位置 58 | String str = "abcdecdedf" 59 | str.indexOf("cde") // => 2 60 | str.indexOf("xyz") // => -1 61 | str.lastIndexOf("cde") // => 5,从后往前 62 | // 仅判断是否存在 63 | str.contains("cde") // => true 64 | str.contains("xyz") // => false 65 | ``` 66 | 67 | ### 去除行首行末空格 68 | ```java 69 | String str = " hello ".trim() // => "hello" 70 | ``` 71 | 72 | ## StringBuilder 73 | > String提供的字符串增删改功能不完善,且效率较低,StringBuilder提供了十分高效的方法 74 | 75 | ### StringBuilder常用方法 76 | 77 | ```java 78 | StringBuilder result = new StringBuilder(); 79 | char[] chars = {'a', 'b', 'c', 'd', 'e'}; 80 | // 尾部添加 81 | result.append(1); // => "1",自动将数字转为字符,不需要额外操作 82 | result.append('2'); // => "12",参数可以是 String, char[],double,int,char等 83 | result.append(chars, 2, 2); // => "12cd",append(chars[], offset, count),后2个参数可选 84 | // 删除 85 | result.delete(1,2); // => "1cd", delete(start, end),不含end 86 | result.deleteCharAt(1); // => "1d" 87 | // 插入 88 | result.insert(0, "abc"); // => "abc1d" // 在某个位置前插入char[],String,int等 89 | // 修改 90 | result.setCharAt(1, 'B'); // => "aBc1d" // 修改 91 | result.setLength(3); // => "aBc",后面的字符将被删除 92 | ``` 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /source/leetcode/46.Permutations.md: -------------------------------------------------------------------------------- 1 | ### [Permutations](https://leetcode.com/problems/permutations/) 2 | 3 | > Given a collection of distinct numbers, return all possible permutations.
4 | > For example,
5 | > * [1,2,3] have the following permutations:
6 | > * [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1]. 7 | 8 | 题目大意:给定一个没有重复数字的集合,返回其排列 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | import java.util.*; 14 | /** 15 | * Created by gzdaijie on 16/5/22 16 | * 递归解法 17 | */ 18 | public class Solution { 19 | public List> permute(int[] nums) { 20 | List> result = new ArrayList>(); 21 | boolean[] flag = new boolean[nums.length]; 22 | ArrayList tmp = new ArrayList(); 23 | permuteRecursion(result, nums, tmp, flag); 24 | return result; 25 | } 26 | 27 | public void permuteRecursion(List> result, int[] nums, ArrayList tmp, boolean[] flag) { 28 | int len = nums.length; 29 | 30 | if (tmp.size() == len) { 31 | result.add((List) tmp.clone()); 32 | return; 33 | } 34 | 35 | for (int i = 0; i < len; i++) { 36 | if (!flag[i]) { 37 | flag[i] = true; 38 | tmp.add(nums[i]); 39 | permuteRecursion(result, nums, tmp, flag); 40 | tmp.remove(tmp.size() - 1); 41 | flag[i] = false; 42 | } 43 | } 44 | } 45 | } 46 | ``` 47 | 48 | ```java 49 | import java.util.*; 50 | /** 51 | * Created by gzdaijie on 16/5/22 52 | * 交换递归解法 53 | */ 54 | public class Solution { 55 | public List> permute(int[] nums) { 56 | List> result = new ArrayList>(); 57 | permuteRecursion(nums, result, 0); 58 | return result; 59 | } 60 | 61 | private void swap(int[] nums, int a, int b) { 62 | if (nums[a] != nums[b]) { 63 | int t = nums[a]; 64 | nums[a] = nums[b]; 65 | nums[b] = t; 66 | } 67 | } 68 | 69 | private void permuteRecursion(int[] nums, List>result, int index) { 70 | int len = nums.length; 71 | if (index == len - 1) { 72 | List tmp = new ArrayList<>(); 73 | for (int i = 0; i < len; tmp.add(nums[i++])); /* empty */ 74 | result.add(tmp); 75 | return; 76 | } 77 | 78 | for (int i = index; i < len; i++) { 79 | swap(nums, index, i); 80 | permuteRecursion(nums, result, index + 1); 81 | swap(nums, i, index); 82 | } 83 | } 84 | } 85 | ``` -------------------------------------------------------------------------------- /source/leetcode/20.Valid Parentheses.md: -------------------------------------------------------------------------------- 1 | [Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) 2 | 3 | > Given a string containing just the characters '(', ')', '{', '}', '[' and ']',
4 | > determine if the input string is valid.
5 | > The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. 6 | 7 | 题目大意:判断括号是否闭合 8 | 9 | 题目难度:Easy 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/6 14 | * 堆栈匹配栈顶和当前字符是否匹配,若栈顶是 }、]、) 直接返回false 15 | */ 16 | public class Solution { 17 | public boolean isValid(String s) { 18 | if (s == null || s.length() == 1)return false; 19 | 20 | int len = s.length(); 21 | Stack stack = new Stack(len); 22 | for (int i = 0; i < len; i++) { 23 | char ch = s.charAt(i); 24 | if (stack.isEmpty()) { 25 | stack.push(s.charAt(i)); 26 | } else { 27 | char peek = stack.peek(); 28 | if (peek == '}' || peek == ']' || peek == ')') return false; 29 | if (peek == '{' && ch == '}' || peek == '[' && ch == ']' || peek == '(' && ch == ')') { 30 | stack.pop(); 31 | } else { 32 | stack.push(ch); 33 | } 34 | } 35 | } 36 | return stack.isEmpty(); 37 | } 38 | 39 | private class Stack { 40 | char[] stack; 41 | int index = -1; 42 | Stack(int n) { 43 | this.stack = new char[n]; 44 | } 45 | public void push(char ch) { 46 | this.stack[++this.index] = ch; 47 | } 48 | public char pop() { 49 | --this.index; 50 | return this.stack[index + 1]; 51 | } 52 | public boolean isEmpty() { 53 | return this.index == -1; 54 | } 55 | public char peek() { 56 | return this.stack[this.index]; 57 | } 58 | } 59 | } 60 | ``` 61 | 62 | ```java 63 | import java.util.Stack; 64 | 65 | /** 66 | * Created by gzdaijie on 16/5/6 67 | * 利用标准库及 ()相差一 []相差二的特性 68 | */ 69 | public class Solution { 70 | public boolean isValid(String s) { 71 | if (s == null || s.length() == 1) return false; 72 | 73 | int len = s.length(); 74 | Stack stack = new Stack(); 75 | for (int i = 0; i < len; i++) { 76 | char ch = s.charAt(i); 77 | if (ch == '(' || ch == '{' || ch == '[') stack.push(ch); 78 | else if (!stack.isEmpty() && Math.abs(ch - stack.peek()) <= 2) stack.pop(); 79 | else return false; 80 | } 81 | return stack.isEmpty(); 82 | } 83 | } 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /source/leetcode/79.Word Search.md: -------------------------------------------------------------------------------- 1 | ### [Word Search](https://leetcode.com/problems/word-search/) 2 | 3 | > Given a 2D board and a word, find if the word exists in the grid.
4 | > The word can be constructed from letters of sequentially adjacent cell,
5 | > where "adjacent" cells are those horizontally or vertically neighboring.
6 | > The same letter cell may not be used more than once.
7 | > For example, Given board =
8 | > [ ['A','B','C','E'],
9 | > ['S','F','C','S'],
10 | > ['A','D','E','E']]
11 | > * word = "ABCCED", -> returns true,
12 | > * word = "SEE", -> returns true,
13 | > * word = "ABCB", -> returns false. 14 | 15 | 题目大意:给定一个矩阵和一个字符串,判断矩阵中连续相邻的元素能否组成该字符串,同一个元素只能用一次。 16 | 17 | 题目难度:Medium 18 | 19 | ```java 20 | /** 21 | * Created by gzdaijie on 16/6/3 22 | * 深度优先搜索,若找到返回true,没有找到,就继续找 23 | */ 24 | public class Solution { 25 | private int[][] dirs = {{1, 0}, {-1, 0},{0, 1}, {0, -1}}; 26 | 27 | public boolean exist(char[][] board, String word) { 28 | if (board == null || board.length == 0) return false; 29 | if (board[0].length == 0) return false; 30 | int m = board.length; 31 | int n = board[0].length; 32 | boolean[][] flag = new boolean[m][n]; 33 | char ch = word.charAt(0); 34 | 35 | for (int i = 0; i < m; i++) { 36 | for (int j = 0; j < n; j++) { 37 | if (board[i][j] == ch) { 38 | flag[i][j] = true; 39 | if (existRecursive(board, flag, word, 1, i, j)) return true; 40 | flag[i][j] = false; 41 | } 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | private boolean existRecursive(char[][] board, boolean[][] flag, String word, int index, int x, int y){ 48 | if (index == word.length()) return true; 49 | 50 | int m = board.length; 51 | int n = board[0].length; 52 | char ch = word.charAt(index); 53 | boolean[] pos = new boolean[4]; 54 | 55 | if (x < m - 1 && !flag[x + 1][y] && board[x + 1][y] == ch) pos[0] = true; 56 | if (x > 0 && !flag[x - 1][y] && board[x - 1][y] == ch) pos[1] = true; 57 | if (y < n - 1 && !flag[x][y + 1] && board[x][y + 1] == ch) pos[2] = true; 58 | if (y > 0 && !flag[x][y - 1] && board[x][y - 1] == ch) pos[3] = true; 59 | 60 | for (int i = 0; i < 4; i++) { 61 | if (!pos[i]) continue; 62 | int _x = x + dirs[i][0]; 63 | int _y = y + dirs[i][1]; 64 | flag[_x][_y] = true; 65 | if(existRecursive(board, flag, word, index + 1, _x, _y)) return true; 66 | flag[_x][_y] = false; 67 | } 68 | return false; 69 | } 70 | } 71 | ``` -------------------------------------------------------------------------------- /source/leetcode/17.Letter Combinations of a Phone Number.md: -------------------------------------------------------------------------------- 1 | ### [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number/) 2 | 3 | > Given a digit string, return all possible letter combinations that the number could represent.
4 | > A mapping of digit to letters (just like on the telephone buttons) is given below.
5 | > * Input:Digit string "23"
6 | > * Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 7 | 8 | 题目大意:给定一个数字组成的字符串,返回所有的这些数字所代表的字母组合。数字字母映射表是与手机上一致 9 | 10 | 题目难度:Medium 11 | 12 | ```java 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by gzdaijie on 16/5/18 18 | * 递归,每一个数字有3-4种情况,遇到每一个数字,遍历其所有可能性即可 19 | */ 20 | public class Solution { 21 | private static final String[] strs = { "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; 22 | 23 | public List letterCombinations(String digits) { 24 | List result = new ArrayList(); 25 | StringBuilder combine = new StringBuilder(); 26 | 27 | if (digits == null || digits.length() == 0) return result; 28 | 29 | letterFullPemutation(result, digits, combine, 0); 30 | return result; 31 | } 32 | 33 | /** 34 | * @param result 存储结果 35 | * @param str 输入的数字 36 | * @param combine 临时变量,存储当前拼接的字符串 37 | * @param k 表示当前已经遍历到的位置 38 | */ 39 | private void letterFullPemutation(List result, String str, StringBuilder combine, int k) { 40 | // 如果遍历完,而且拼接的字符串不为空,则加入结果当中 41 | if (k == str.length()) { 42 | if (combine.length() > 0) { 43 | result.add(combine.toString()); 44 | } 45 | return; 46 | } 47 | 48 | int index = str.charAt(k) - '2'; 49 | if (index < 0) { 50 | letterFullPemutation(result, str, combine, k + 1); 51 | } else { 52 | int len = strs[index].length(); 53 | for (int i = 0; i < len; i++) { 54 | combine.append(strs[index].charAt(i)); 55 | letterFullPemutation(result, str, combine, k + 1); 56 | combine.setLength(combine.length() - 1); 57 | } 58 | } 59 | } 60 | } 61 | ``` 62 | 63 | ```java 64 | import java.util.*; 65 | 66 | /** 67 | * Created by gzdaijie on 16/5/18 68 | * BFS,使用队列实现,每次出队的子串,依次添加当前数字对应的字母,再入队 69 | */ 70 | public class Solution { 71 | private static final String[] strs = { "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; 72 | 73 | public List letterCombinations(String digits) { 74 | Queue result = new LinkedList<>(); 75 | if (digits == null || digits.length() == 0) return new ArrayList<>(result); 76 | 77 | String str = strs[digits.charAt(0) - '2']; 78 | int len = str.length(); 79 | for (int i = 0; i < len; i++) { 80 | result.add(str.charAt(i) + ""); 81 | } 82 | 83 | for (int i = 1; i < digits.length(); i++) { 84 | int size = result.size(); 85 | while (size-- > 0) { 86 | String prefix = result.poll(); 87 | str = strs[digits.charAt(i) - '2']; 88 | len = str.length(); 89 | for (int j = 0; j < len; j++) { 90 | result.add(prefix + str.charAt(j)); 91 | } 92 | } 93 | } 94 | return new ArrayList<>(result); 95 | } 96 | } 97 | ``` -------------------------------------------------------------------------------- /source/leetcode/4.Median of Two Sorted Arrays.md: -------------------------------------------------------------------------------- 1 | ### [Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/) 2 | 3 | > There are two sorted arrays nums1 and nums2 of size m and n respectively.
4 | > Find the median of the two sorted arrays.
5 | > The overall run time complexity should be O(log (m+n)). 6 | 7 | 题目大意:给定2个已排序好的数组(大小分别为M和N),找出2个数组中所有数的中位数,时间复杂度 O(log(M+N)) 8 | 9 | 题目难度:Hard 10 | 11 | ```java 12 | /** 13 | * Created by gzdaijie on 16/5/3 14 | * 新建一个数组(M+N),遍历2个数组进行排序,再取新数组的中位数 15 | * 因为给定数组是有序的,复杂度为O(M+N),居然能A 16 | * 当然有很多改进的地方,(1)遍历到总长度一半时停止,(2)不需要新建数组,2个临时变量,存下mid和mid-1 17 | * 但是仍改变不了复杂度是O(M+N)的事实 18 | */ 19 | public class Solution { 20 | public double findMedianSortedArrays(int[] nums1, int[] nums2) { 21 | int len1 = nums1.length; 22 | int len2 = nums2.length; 23 | // 其中一个为空,返回另一个数组的中位数 24 | if (len1 == 0) return this.getMedian(nums2); 25 | if (len2 == 0) return this.getMedian(nums1); 26 | // t1和t2指针分别指向nums1和nums2,较小的值赋值给nums,指针前移 27 | int t1 = 0; 28 | int t2 = 0; 29 | int index = 0; 30 | int[] nums = new int[len1 + len2]; 31 | while (t1 < len1 && t2 < len2) { 32 | if(nums1[t1] <= nums2[t2]) { 33 | nums[index++] = nums1[t1++]; 34 | } else { 35 | nums[index++] = nums2[t2++]; 36 | } 37 | } 38 | // 剩下部分继续赋值 39 | if (t1 == len1) { 40 | while (t2 < len2) { 41 | nums[index++] = nums2[t2++]; 42 | } 43 | } else { 44 | while (t1 < len1) { 45 | nums[index++] = nums1[t1++]; 46 | } 47 | } 48 | return this.getMedian(nums); 49 | } 50 | 51 | public double getMedian(int[] nums) { 52 | int flag = (nums.length + 1) % 2; 53 | int mid = nums.length / 2; 54 | return (nums[mid] + nums[mid - flag]) / 2.0; 55 | } 56 | } 57 | ``` 58 | 59 | ```java 60 | /** 61 | * Created by gzdaijie on 16/5/3. 62 | * 假设求第k大的数, 切2个有序数组,(Left1, Right1) (Left2, Right2), Left1.length + Left2.length == k 63 | * 记Left1的最大值为L1, Right1的最大值为R1, 那么如果L1 < R2 && L2 < R1, 那么第k大的数字就是 max(L1, L2) 64 | * 首先,nums1的切口在c1(c1初始值为k),nums2切口在k-c1, L1 > R2, c1需减小,L2 > R1, c1需增大 65 | * 切口位置可以使用二分法确定, 例如L1 > R2, c1需要减少,说明c1右边的切位都被排除,end = c1, 反之 start = c1 66 | * c1 = (start + end)/2 67 | * 复杂度 O(log(M+N)) 68 | */ 69 | public class Solution { 70 | public double findMedianSortedArrays(int[] nums1, int[] nums2) { 71 | int len1 = nums1.length; 72 | int len2 = nums2.length; 73 | int len = len1 + len2; 74 | // 一方为空,返回另一数组的中值 75 | if (len1 == 0) return this.getMedian(nums2); 76 | if (len2 == 0) return this.getMedian(nums1); 77 | 78 | // 确保len1小于len2,减少二分次数 79 | if (len1 > len2) { 80 | return findMedianSortedArrays(nums2, nums1); 81 | } 82 | // mid 中间位置, c1,c2记录切的位置, start,end用于二分确定切的位置 83 | int mid = len/2; 84 | int c1, c2; 85 | int start, end; 86 | int l1,l2,r1,r2; 87 | int MIN = Integer.MIN_VALUE; 88 | int MAX = Integer.MAX_VALUE; 89 | 90 | start = 0; 91 | end = c1 = mid > len1 ? len1 : mid; 92 | c2 = mid - c1; 93 | 94 | while (true) { 95 | l1 = c1 == 0 ? MIN : nums1[c1 - 1]; 96 | l2 = c2 == 0 ? MIN : nums2[c2 - 1]; 97 | r1 = c1 == len1 ? MAX : nums1[c1]; 98 | r2 = c2 == len2 ? MAX : nums2[c2]; 99 | 100 | if (l1 <= r2 && l2 <= r1) { 101 | break; 102 | } 103 | if (l2 > r1) { 104 | start = c1; 105 | } else { 106 | end = c1; 107 | } 108 | c1 = (start + end)/ 2; 109 | c2 = mid - c1; 110 | } 111 | 112 | if(len % 2 == 0) { 113 | return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0; 114 | } else { 115 | return Math.min(r1, r2) * 1.0; 116 | } 117 | 118 | } 119 | 120 | public double getMedian(int[] nums) { 121 | int flag = (nums.length + 1) % 2; 122 | int mid = nums.length / 2; 123 | return (nums[mid] + nums[mid - flag]) / 2.0; 124 | } 125 | } 126 | ``` 127 | 128 | > 参考:[leetCode讨论区](https://leetcode.com/discuss/99245/leetbook-%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E4%B8%AD%E5%80%BC%E9%97%AE%E9%A2%98%EF%BC%8C%E5%88%86%E6%AD%A5%E8%AF%A6%E8%A7%A3%EF%BC%88%E9%99%84%E8%A7%A3%E9%87%8A%EF%BC%8C%E5%9B%BE%E7%A4%BA%EF%BC%8C%E4%BB%A3%E7%A0%81%EF%BC%89) -------------------------------------------------------------------------------- /source/leetcode/5.Longest Palindromic Substring.md: -------------------------------------------------------------------------------- 1 | ### [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) 2 | 3 | > Given a string S, find the longest palindromic substring in S.
4 | > You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 5 | 6 | 题目大意:寻找给定字符串(长度不超过1000)的最长回文子串,回文子串存在且唯一 7 | 8 | 题目难度:Medium 9 | 10 | ```java 11 | /** 12 | * Created by gzdaijie on 16/5/3 13 | * 回文字符串只有2种形式, abba,aba 14 | * (1) 遍历字符,查看其左右是否相等, 更新start,end 15 | * (2) 遍历字符,如果右边与当前字符相等,查看这2个字符的左右是否相等, 更新start,end 16 | * 若最长回文串长度为K,最坏复杂度为O(K*N) 17 | */ 18 | public class Solution { 19 | public String longestPalindrome(String s) { 20 | int len = s.length(); 21 | int start = 0, end = 0; 22 | 23 | for (int i = 0; i < len; ++i) { 24 | // 情况1: aba,奇数回文串 25 | int k = 1; 26 | while (i - k >= 0 && i + k < len && s.charAt(i - k) == s.charAt(i + k)) ++k; 27 | if (end - start < 2 * k - 1) { 28 | start = i - k + 1; 29 | end = i + k; 30 | } 31 | // 情况2: abba,偶数回文串 32 | k = 0; 33 | while (i - k >= 0 && i + k + 1 < len && s.charAt(i - k) == s.charAt(i + k + 1)) ++k; 34 | if (end - start < 2 * k) { 35 | start = i - k + 1; 36 | end = i + k + 1; 37 | } 38 | } 39 | return s.substring(start, end); 40 | } 41 | } 42 | ``` 43 | 44 | ```java 45 | /** 46 | * Created by gzdaijie on 16/5/3 47 | * 首先所有字符都相同的字符串无论字符多少,都是回文字符串 48 | * 对于有连续相等的字符的字符串, zxyyyyyyxa,只需找到连续相等的y的第一个和最后一个位置,判断左右即可 49 | * 遍历时,可直接从第一个y的位置跳到最后一个y下一位 50 | * 当字符有1000个,连续出现同一字符概率很大,因此此算法非常高效,但是若无连续出现字符,仍为O(N*K) 51 | */ 52 | public class Solution { 53 | public String longestPalindrome(String s) { 54 | int len = s.length(); 55 | int max = 0; 56 | int start = 0; 57 | int end = 0; 58 | 59 | for (int i = 0; i < len;) { 60 | int index = this.getFarestSameChar(s, i); 61 | int dist = this.getDistance(s,i ,index); 62 | int p = i - dist; 63 | int q = index + dist; 64 | if (q - p + 1 > max) { 65 | start = p; 66 | end = q; 67 | max = end - start + 1; 68 | } 69 | i = index + 1; // 从i->index的字符都是相等的,因此可以直接跳过 70 | } 71 | return s.substring(start, end + 1); 72 | 73 | } 74 | 75 | /** 76 | * 判断左右是回文字符的个数 77 | */ 78 | private int getDistance(String s, int start, int end) { 79 | int len = s.length(); 80 | int dist = 0; 81 | 82 | start -= 1; 83 | end += 1; 84 | while (start >= 0 && end < len) { 85 | if (s.charAt(start) != s.charAt(end)) break; 86 | --start; 87 | ++end; 88 | ++dist; 89 | } 90 | return dist; 91 | } 92 | 93 | /** 94 | * 连续字符,最远的一个下标 95 | */ 96 | private int getFarestSameChar(String s, int index) { 97 | int len = s.length(); 98 | char ch = s.charAt(index); 99 | for (int i = index + 1; i < len; ++i) { 100 | if (ch != s.charAt(i))return i - 1; 101 | } 102 | return len - 1; 103 | } 104 | } 105 | ``` 106 | 107 | ```java 108 | /** 109 | * Created by gzdaijie on 16/5/4 110 | * Manacher 算法 111 | * 使用#扩展字符串解决奇偶回文字符串问题 112 | * 使用数组RL和对称中心pos,避免重复计算 113 | * 复杂度O(N),分析见参考 114 | * 但是在leetcode上运行时间超过以上2种,原因未知 115 | */ 116 | public class Solution { 117 | public String longestPalindrome(String s) { 118 | String str = this.addSharpToString(s); 119 | 120 | int len = str.length(); 121 | int max, start, end; 122 | int maxRight, pos; 123 | int[] RL = new int[len]; 124 | 125 | max = start = end = maxRight = pos = 0; 126 | for (int i = 0; i < len; ++i) { 127 | // 如果i在maxRight的左边,初始值设置为i的对称位的值 128 | if (i < maxRight) { 129 | RL[i] = Math.min(RL[2 * pos - i], maxRight - i + 1); 130 | } else { 131 | RL[i] = 1; 132 | } 133 | // 尝试对i进行扩展 134 | while (i - RL[i] >= 0 && i + RL[i] < len) { 135 | if (str.charAt(i - RL[i]) != str.charAt(i + RL[i])) break; 136 | RL[i]++; 137 | } 138 | // 更新最大右边界与对称中心 139 | if (i + RL[i] - 1 > maxRight) { 140 | maxRight = RL[i] + i - 1; 141 | pos = i; 142 | } 143 | // 更新 max与首末位置 144 | if (RL[i] > max) { 145 | max = RL[i]; 146 | start = i- RL[i] + 1; 147 | end = i + RL[i] - 1; 148 | } 149 | } 150 | // 去掉#,连接字符串并返回 151 | String result = ""; 152 | String[] strings = str.substring(start, end + 1).split("#"); 153 | len = strings.length; 154 | for (int i = 0; i < len; i++) { 155 | result += strings[i]; 156 | } 157 | return result; 158 | } 159 | private String addSharpToString(String s) { 160 | int len = s.length(); 161 | String str = "#"; 162 | for (int i = 0; i < len; ++i) { 163 | str += s.charAt(i) + "#"; 164 | } 165 | return str; 166 | } 167 | } 168 | ``` 169 | 170 | > 参考:[最长回文子串——Manacher 算法](https://segmentfault.com/a/1190000003914228) 171 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | Leetcode Java 2 | * Leetcode练习题 3 | * [1.Two Sum](source/leetcode/1.Two Sum.md) 4 | * [2.Add Two Numbers](source/leetcode/2.Add Two Numbers.md) 5 | * [3.Longest Substring Without Repeating Characters](source/leetcode/3.Longest Substring Without Repeating Characters.md) 6 | * [4.Median of Two Sorted Arrays](source/leetcode/4.Median of Two Sorted Arrays.md) 7 | * [5.Longest Palindromic Substring](source/leetcode/5.Longest Palindromic Substring.md) 8 | * [6.ZigZag Conversion](source/leetcode/6.ZigZag Conversion.md) 9 | * [7.Reverse Integer](source/leetcode/7.Reverse Integer.md) 10 | * [8.String to Integer (atoi)](source/leetcode/8.String to Integer (atoi).md) 11 | * [9.Palindrome Number](source/leetcode/9.Palindrome Number.md) 12 | * [11.Container With Most Water](source/leetcode/11.Container With Most Water.md) 13 | * [13.Roman to Integer](source/leetcode/13.Roman to Integer.md) 14 | * [14.Longest Common Prefix](source/leetcode/14.Longest Common Prefix.md) 15 | * [15.3Sum](source/leetcode/15.3Sum.md) 16 | * [16.3Sum Closest](source/leetcode/16.3Sum Closest.md) 17 | * [17.Letter Combinations of a Phone Number](source/leetcode/17.Letter Combinations of a Phone Number.md) 18 | * [18.4Sum](source/leetcode/18.4Sum.md) 19 | * [19.Remove Nth Node From End of List](source/leetcode/19.Remove Nth Node From End of List.md) 20 | * [20.Valid Parentheses](source/leetcode/20.Valid Parentheses.md) 21 | * [21.Merge Two Sorted Lists](source/leetcode/21.Merge Two Sorted Lists.md) 22 | * [22.Generate Parentheses](source/leetcode/22.Generate Parentheses.md) 23 | * [23.Merge k Sorted Lists](source/leetcode/23.Merge k Sorted Lists.md) 24 | * [24.Swap Nodes in Pairs](source/leetcode/24.Swap Nodes in Pairs.md) 25 | * [26.Remove Duplicates from Sorted Array](source/leetcode/26.Remove Duplicates from Sorted Array.md) 26 | * [27.Remove Element](source/leetcode/27.Remove Element.md) 27 | * [28.Implement strStr()](source/leetcode/28.Implement strStr().md) 28 | * [31.Next Permutation](source/leetcode/31.Next Permutation.md) 29 | * [34.Search for a Range](source/leetcode/34.Search for a Range.md) 30 | * [35.Search Insert Position](source/leetcode/35.Search Insert Position.md) 31 | * [36.Valid Sudoku](source/leetcode/36.Valid Sudoku.md) 32 | * [38.Count and Say](source/leetcode/38.Count and Say.md) 33 | * [39.Combination Sum](source/leetcode/39.Combination Sum.md) 34 | * [40.Combination Sum II](source/leetcode/40.Combination Sum II.md) 35 | * [41.First Missing Positive](source/leetcode/41.First Missing Positive.md) 36 | * [42.Trapping Rain Water](source/leetcode/42.Trapping Rain Water.md) 37 | * [43.Multiply Strings](source/leetcode/43.Multiply Strings.md) 38 | * [46.Permutations](source/leetcode/46.Permutations.md) 39 | * [47.Permutations II](source/leetcode/47.Permutations II.md) 40 | * [48.Rotate Image](source/leetcode/48.Rotate Image.md) 41 | * [49.Group Anagrams](source/leetcode/49.Group Anagrams.md) 42 | * [50.Pow(x, n)](source/leetcode/50.Pow(x, n).md) 43 | * [53.Maximum Subarray](source/leetcode/53.Maximum Subarray.md) 44 | * [54.Spiral Matrix](source/leetcode/54.Spiral Matrix.md) 45 | * [55.Jump Game](source/leetcode/55.Jump Game.md) 46 | * [58.Length of Last Word](source/leetcode/58.Length of Last Word.md) 47 | * [59.Spiral Matrix II](source/leetcode/59.Spiral Matrix II.md) 48 | * [60.Permutation Sequence](source/leetcode/60.Permutation Sequence.md) 49 | * [61.Rotate List](source/leetcode/61.Rotate List.md) 50 | * [62.Unique Paths](source/leetcode/62.Unique Paths.md) 51 | * [63.Unique Paths II](source/leetcode/63.Unique Paths II.md) 52 | * [64.Minimum Path Sum](source/leetcode/64.Minimum Path Sum.md) 53 | * [66.Plus One](source/leetcode/66.Plus One.md) 54 | * [67. Add Binary](source/leetcode/67. Add Binary.md) 55 | * [69.Sqrt(x)](source/leetcode/69.Sqrt(x).md) 56 | * [70.Climbing Stairs](source/leetcode/70.Climbing Stairs.md) 57 | * [71.Simplify Path](source/leetcode/71.Simplify Path.md) 58 | * [73.Set Matrix Zeroes](source/leetcode/73.Set Matrix Zeroes.md) 59 | * [74.Search a 2D Matrix](source/leetcode/74.Search a 2D Matrix.md) 60 | * [75.Sort Colors](source/leetcode/75.Sort Colors.md) 61 | * [77.Combinations](source/leetcode/77.Combinations.md) 62 | * [78.Subsets](source/leetcode/78.Subsets.md) 63 | * [79.Word Search](source/leetcode/79.Word Search.md) 64 | * [80.Remove Duplicates from Sorted Array II](source/leetcode/80.Remove Duplicates from Sorted Array II.md) 65 | * [82.Remove Duplicates from Sorted List II](source/leetcode/82.Remove Duplicates from Sorted List II.md) 66 | * [83.Remove Duplicates from Sorted List](source/leetcode/83.Remove Duplicates from Sorted List.md) 67 | * [86.Partition List](source/leetcode/86.Partition List.md) 68 | * [88.Merge Sorted Array](source/leetcode/88.Merge Sorted Array.md) 69 | * [89.Gray Code](source/leetcode/89.Gray Code.md) 70 | * [90.Subsets II](source/leetcode/90.Subsets II.md) 71 | * [91.Decode Ways](source/leetcode/91.Decode Ways.md) 72 | * [92.Reverse Linked List II](source/leetcode/92.Reverse Linked List II.md) 73 | * [93.Restore IP Addresses](source/leetcode/93.Restore IP Addresses.md) 74 | * [94.Binary Tree Inorder Traversal](source/leetcode/94.Binary Tree Inorder Traversal.md) 75 | * [96.Unique Binary Search Trees](source/leetcode/96.Unique Binary Search Trees.md) 76 | * [98.Validate Binary Search Tree](source/leetcode/98.Validate Binary Search Tree.md) 77 | * [100.Same Tree](source/leetcode/100.Same Tree.md) 78 | * [101.Symmetric Tree](source/leetcode/101.Symmetric Tree.md) 79 | * [102.Binary Tree Level Order Traversal](source/leetcode/102.Binary Tree Level Order Traversal.md) 80 | * [103.Binary Tree Zigzag Level Order Traversal](source/leetcode/103.Binary Tree Zigzag Level Order Traversal.md) 81 | * [104.Maximum Depth of Binary Tree](source/leetcode/104.Maximum Depth of Binary Tree.md) 82 | * [105.Construct Binary Tree from Preorder and Inorder](source/leetcode/105.Construct Binary Tree from Preorder and Inorder.md) 83 | * [106.Construct Binary Tree from Inorder and Postord](source/leetcode/106.Construct Binary Tree from Inorder and Postord.md) 84 | * [107.Binary Tree Level Order Traversal II](source/leetcode/107.Binary Tree Level Order Traversal II.md) 85 | * [108.Convert Sorted Array to Binary Search Tree](source/leetcode/108.Convert Sorted Array to Binary Search Tree.md) 86 | * [109.Convert Sorted List to Binary Search Tree](source/leetcode/109.Convert Sorted List to Binary Search Tree.md) 87 | * [110.Balanced Binary Tree](source/leetcode/110.Balanced Binary Tree.md) 88 | * [111.Minimum Depth of Binary Tree](source/leetcode/111.Minimum Depth of Binary Tree.md) 89 | * [112.Path Sum](source/leetcode/112.Path Sum.md) 90 | * [113.Path Sum II](source/leetcode/113.Path Sum II.md) 91 | * [114.Flatten Binary Tree to Linked List](source/leetcode/114.Flatten Binary Tree to Linked List.md) 92 | * [116.Populating Next Right Pointers in Each Node](source/leetcode/116.Populating Next Right Pointers in Each Node.md) 93 | * [117.Populating Next Right Pointers in Each Node II](source/leetcode/117.Populating Next Right Pointers in Each Node II.md) 94 | * [118.Pascal's Triangle](source/leetcode/118.Pascal's Triangle.md) 95 | * [119.Pascal's Triangle II](source/leetcode/119.Pascal's Triangle II.md) 96 | * [120.Triangle](source/leetcode/120.Triangle.md) 97 | * [121.Best Time to Buy and Sell Stock](source/leetcode/121.Best Time to Buy and Sell Stock.md) 98 | * [122.Best Time to Buy and Sell Stock II](source/leetcode/122.Best Time to Buy and Sell Stock II.md) 99 | * [125.Valid Palindrome](source/leetcode/125.Valid Palindrome.md) 100 | * [129.Sum Root to Leaf Numbers](source/leetcode/129.Sum Root to Leaf Numbers.md) 101 | * [136.Single Number](source/leetcode/136.Single Number.md) 102 | * [137.Single Number II](source/leetcode/137.Single Number II.md) 103 | * [141.Linked List Cycle](source/leetcode/141.Linked List Cycle.md) 104 | * [169.Majority Element](source/leetcode/169.Majority Element.md) 105 | * [344.Reverse String](source/leetcode/344.Reverse String.md) 106 | * Java类库 107 | * [1. Array](tips/Array.md) 108 | * [2. Char](tips/Char.md) 109 | * [3. HashMap](tips/HashMap.md) 110 | * [4. IO](tips/IO.md) 111 | * [5. List](tips/List.md) 112 | * [6. Math](tips/Math.md) 113 | * [7. Queue](tips/Queue.md) 114 | * [8. Stack](tips/Stack.md) 115 | * [9. String](tips/String.md) 116 | --------------------------------------------------------------------------------