34. Search for a Range
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1]. For example, Given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4]. 思路:二分法选择后,进行前后遍历获取角标。 注意:边界条件的放置; 边界条件需提前考虑进去;可以放在思维架构图后做补充,然后写代码调试; 二分法的mid + 1和mid - 1不试不知道,一试吓一跳,可以从Solution里看到重复多少判断!
1 public class Solution { 2 public int[] searchRange(int[] A, int target) { 3 int start = Solution.firstGreaterEqual(A, target); 4 if (start == A.length || A[start] != target) { 5 return new int[]{-1, -1}; 6 } 7 return new int[]{start, Solution.firstGreaterEqual(A, target + 1) - 1}; 8 } 9 10 //find the first number that is greater than or equal to target. 11 //could return A.length if target is greater than A[A.length-1]. 12 //actually this is the same as lower_bound in C++ STL. 13 private static int firstGreaterEqual(int[] A, int target) { 14 int low = 0, high = A.length; 15 while (low < high) { 16 int mid = low + ((high - low) >> 1); 17 //low <= mid < high 18 if (A[mid] < target) { 19 low = mid + 1; 20 } else { 21 //should not be mid-1 when A[mid]==target. 22 //could be mid even if A[mid]>target because mid<high. 23 high = mid; 24 } 25 } 26 return low; 27 } 28 }
1 package LeetCode; 2 3 /** 4 * Created by BlueMond on 2017/12/20. 5 */ 6 public class SearchforRange { 7 public int[] searchRange(int[] nums, int target) { 8 //中序查找法 9 int numsLength = nums.length; 10 int mid = numsLength/2; 11 int left = 0; 12 int right = numsLength - 1; 13 int[] result = {-1, -1}; 14 int outLeft = 0; 15 int outRight = 0; 16 int tmp = 0; 17 if(numsLength == 0 ){ 18 return result; 19 } 20 21 22 while (left != right && tmp != mid){ 23 tmp = mid; 24 if(target < nums[mid]){ 25 right = mid; 26 mid = (left + right)/2; 27 } 28 else if(target > nums[mid]){ 29 left = mid; 30 mid = (left + right)/2; 31 }else { 32 break; 33 } 34 35 } 36 37 if(nums[mid] != target){ 38 if(mid + 1 < numsLength && nums[mid + 1] != target){ 39 return result; 40 }else if (mid + 1 < numsLength && nums[mid + 1] == target){ 41 result[0] = mid + 1; 42 result[1] = mid + 1; 43 return result; 44 } 45 } 46 47 outLeft = mid; 48 outRight = mid; 49 50 while (outLeft >= 0 && nums[outLeft] == target){ 51 outLeft--; 52 } 53 while (outRight < numsLength && nums[outRight] == target){ 54 outRight++; 55 }//良好的习惯是边界条件放最左边; 56 if(outLeft != mid){ 57 result[0] = outLeft + 1; 58 } 59 if (outRight != mid){ 60 result[1] = outRight - 1;} 61 return result; 62 } 63 public static void main(String[] args){ 64 int[] input = {1}; 65 int needle = 0; 66 int[] output = new SearchforRange().searchRange(input, needle); 67 System.out.println(output[0]); 68 } 69 }
22. Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n = 3, a solution set is: [ "((()))", "(()())", "(())()", "()(())", "()()()" ] 思路:采用递归算法,利用左括号和右括号的增加法,生成全部的列表内容,得到结果。
1 class Solution { 2 public List<String> generateParenthesis(int n) { 3 4 List<String> list = new ArrayList<String>(); 5 backtrack(list, "", 0, 0, n); 6 return list; 7 } 8 9 public void backtrack(List<String> list, String str, int open, int close, int max){ 10 11 if(str.length() == max*2){ 12 list.add(str); 13 return; 14 } 15 16 if(open < max) 17 backtrack(list, str+"(", open+1, close, max); 18 if(close < open) 19 backtrack(list, str+")", open, close+1, max); 20 21 } 22 }
21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 思路:递归思想参 http://www.cnblogs.com/cenmny/p/7906311.html(递归“赏析”)。
1 class Solution { 2 public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 3 if(l1 == null){ 4 return l2; 5 } 6 if(l2 == null){ 7 return l1; 8 } 9 ListNode merge; 10 if(l1.val < l2.val){ 11 merge = l1; 12 merge.next = mergeTwoLists(l1.next, l2); 13 return l1; 14 }else { 15 merge = l2; 16 merge.next = mergeTwoLists(l1, l2.next); 17 return l2; 18 } 19 } 20 }
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode(int x) { val = x; } 7 * } 8 */ 9 class Solution { 10 public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 11 ListNode n1 = l1; 12 ListNode n2 = l2; 13 ListNode l3 = new ListNode(0); 14 ListNode n3 = l3; 15 16 while(n1 != null && n2 != null){ 17 if(n1.val <= n2.val){ 18 n3.next = new ListNode(n1.val); 19 n1 = n1.next; 20 }else{ 21 n3.next = new ListNode(n2.val); 22 n2 = n2.next; 23 } 24 n3 = n3.next; 25 } 26 if(n1 == null){ 27 n3.next = n2; 28 }else{ 29 n3.next = n1; 30 } 31 32 return l3.next; 33 } 34 }
20. Valid Parentheses
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. 思路:栈的灵魂引用;核心Stack自带方法有(Stack stk) stk.isEmpty(), stk.peek(), stk.push(), stk.pop().
同时应用了链表的 .add(Object o)function.
1 package LeetCode; 2 import java.util.ArrayList; 3 import java.util.Stack; 4 /** 5 * Created by BlueMond on 2017/11/22. 6 */ 7 public class ValidParentheses { 8 public boolean isValid(String s) { 9 if(s.length() % 2 != 0){ 10 return false; 11 } 12 int j = 0; 13 ArrayList<Character> a = new ArrayList(); 14 a.add('('); 15 a.add(')'); 16 a.add('{'); 17 a.add('}'); 18 a.add('['); 19 a.add(']'); 20 Stack<Character> result = new Stack<>(); 21 22 for(int i = 0; i < s.length(); i++){ 23 j = a.indexOf(s.charAt(i)); 24 if(result.empty()){ 25 result.push(s.charAt(i)); 26 }else if ((a.indexOf(result.peek()) % 2 ==0 && a.indexOf(result.peek()) + 1 == j)){ 27 result.pop(); 28 }else { 29 result.push(s.charAt(i)); 30 } 31 } 32 return result.empty(); 33 } 34 public static void main(String[] args){ 35 String input = ""; 36 boolean output = new ValidParentheses().isValid(input); 37 System.out.print(output); 38 } 39 }
19. Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head. For example, Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5. Note: Given n will always be valid. Try to do this in one pass. 思路:第一种,获得input的长度,然后找到要删除的位置,切记删除的要是tmp.next,以满足tmp.next = tmp.next.next条件,不能直接对tmp操作,否则会失去tmp对原链表head的绑定;
第二种better解法,fast和slow同时绑定head,fast前进到n处后,fast与slow同时前进以满足slow定位到要删节点处,完成删除。
1 public ListNode removeNthFromEnd(ListNode head, int n) { 2 3 ListNode start = new ListNode(0); 4 ListNode slow = start, fast = start; 5 slow.next = head; 6 7 //Move fast in front so that the gap between slow and fast becomes n 8 for(int i=1; i<=n+1; i++) { 9 fast = fast.next; 10 } 11 //Move fast to the end, maintaining the gap 12 while(fast != null) { 13 slow = slow.next; 14 fast = fast.next; 15 } 16 //Skip the desired node 17 slow.next = slow.next.next; 18 return start.next; 19 }
1 package LeetCode; 2 3 /** 4 * Created by BlueMond on 2017/11/22. 5 */ 6 public class RemoveEndofList { 7 8 public ListNode removeNthFromEnd(ListNode head, int n) { 9 10 ListNode tmp = head; 11 // head = null; 12 int length = 0; 13 14 while(tmp != null){ 15 length++; 16 tmp = tmp.next; 17 } 18 if(length == n){ 19 head = head.next; 20 return head; 21 } 22 tmp = head; 23 for(int i = 0; i < length - n-1; i++){ 24 tmp = tmp.next; 25 } 26 tmp.next = tmp.next.next; 27 return head; 28 29 } 30 public static void main(String[] args){ 31 ListNode head = new ListNode(1); 32 head.next = new ListNode(2); 33 ListNode output = new RemoveEndofList().removeNthFromEnd(head,1); 34 System.out.print(output.val + " " + "output.next.val"); 35 } 36 }
17. Letter Combinations of a Phone Number
Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Input:Digit string "23" Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 思路:使用队列法,遍历输入的数字;第一个数字对应的按键字母存入List中;第二个数字进入时,把List中的String按序取出,每个String都加上第二个数字对应的3或4个字母;加入结果存储完成。
注意 new LinkedList<>()初始化时无内容,即 LL.peek() == null, 建议LL.add("")做后续操作;
1 package LeetCode; 2 import java.util.LinkedList; 3 import java.util.List; //引入时不用注明类型 4 /** 5 * Created by BlueMond on 2017/11/21. 6 */ 7 public class LetterPhoneNumber { 8 9 public List<String> firstPart(String input){ 10 11 12 String[] mapping = {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; 13 LinkedList<String> output = new LinkedList<String>(); 14 if(input.length() == 0){ 15 return output; 16 } 17 output.add(""); 18 int tmp = 0; 19 20 for(int i = 0; i < input.length(); i++){ 21 tmp = input.charAt(i) - '0'; 22 while (output.peek().length() == i){ 23 String outQueue = output.remove(); 24 for(char j : mapping[tmp].toCharArray()){ 25 output.add(outQueue + j); 26 } 27 } 28 } 29 return output; 30 } 31 public static void main(String[] args){ 32 String input = "23"; 33 List<String> output = new LetterPhoneNumber().firstPart(input); 34 System.out.print(output.get(0) + " " + output.get(1)); 35 } 36 37 }
14. Longest Common Prefix
灵活运用String[]自带的方法: 1. Arrays.sort()在字符串中的应用,会基于角标数的增加进行相应char的排序; 2. String1.indexOf(String2)的应用,有会返回0,无返回-1; 3. String1.subString(int begin, int end)的应用,返回从begin开始到end前一位的字符串。
1 package LeetCode; 2 import java.lang.Math; 3 import java.util.Arrays; 4 5 /** 6 * Created by BlueMond on 2017/11/15. 7 */ 8 public class LongestCommonPrefix { 9 10 public String better(String[] strs) { 11 StringBuilder result = new StringBuilder(); 12 13 if (strs!= null && strs.length > 0){ 14 15 Arrays.sort(strs); 16 17 char [] a = strs[0].toCharArray(); 18 char [] b = strs[strs.length-1].toCharArray(); 19 20 for (int i = 0; i < a.length; i ++){ 21 if (b.length > i && b[i] == a[i]){ 22 result.append(b[i]); 23 } 24 else { 25 return result.toString(); 26 } 27 }} 28 return result.toString(); 29 } 30 31 public String firstPart(String[] input){ 32 if(input.length == 0){ 33 return ""; 34 } 35 int length = input[0].length(); 36 int lengthLong = input.length; 37 int tmp = 0; 38 char tmpChar = 0; 39 int k = 0; 40 StringBuffer result = new StringBuffer(); 41 for(int i = 0; i < lengthLong; i++){ 42 if(input[i].length() < length){ 43 length = input[i].length(); 44 tmp = i; 45 } 46 } 47 for(; k < length; k++){ 48 tmpChar = input[tmp].charAt(k); 49 result.append(tmpChar); 50 for(int j = 0; j < lengthLong; j++){ 51 if(input[j].charAt(k) != tmpChar){ 52 return result.deleteCharAt(k).toString(); 53 } 54 } 55 } 56 return result.toString(); 57 } 58 public static void main(String[] args){ 59 String[] input = {"abcder", "abc", "aabd"}; 60 String pre = "abcdefg"; 61 pre = pre.substring(1,2); 62 String output = new LongestCommonPrefix().better(input); 63 System.out.println(pre); 64 } 65 }
13. Roman to Integer
阿拉伯数字和罗马数字的互转,较简单。1.使用数组对应法;2.使用Map寻值法。
package LeetCode; import java.util.HashMap; /** * Created by BlueMond on 2017/11/15. */ public class IntegerToRoman { public String firstPart(int num){ String[] lData1 = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; String[] lData2 = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; String[] lData3 = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; String[] lData4 = {"", "M", "MM", "MMM"}; if(num < 1 || num > 3999){ return "-1"; } return lData4[num / 1000] + lData3[num % 1000 / 100] + lData2[num % 100 / 10] + lData1[num % 10 ]; } public int secondPart(String s){ HashMap<Character, Integer> hm = new HashMap<>(); hm.put('I', 1); hm.put('V', 5); hm.put('X', 10); hm.put('L', 50); hm.put('C', 100); hm.put('D', 500); hm.put('M', 1000); int sum = 0; for(int i = 1; i < s.length(); i++){ if(hm.get(s.charAt(i - 1)) < hm.get(s.charAt(i))){ sum += - hm.get(s.charAt(i - 1)); } else { sum += hm.get(s.charAt(i - 1)); } } return sum += hm.get(s.charAt(s.length() - 1)); } }
8. String to Integer (atoi)
思路:
1.注意边界条件,相同正负号只会出现一次; 2.Integer.valueOf(char[i])返回的是ascll码值,不是对应的int值; 3.Character.isDigit(char[i])可判断对应位置char是否为数字; 4.sum = sum * 10 + str.charAt(i) - '0'; 机智啊,就是用ascll码值的处理。
1 public static int myAtoi(String str) { 2 if (str == null || str.length() == 0) 3 return 0;// 4 str = str.trim(); 5 char firstChar = str.charAt(0); 6 int sign = 1, start = 0, len = str.length(); 7 long sum = 0; 8 if (firstChar == '+') { 9 sign = 1; 10 start++; 11 } else if (firstChar == '-') { 12 sign = -1; 13 start++; 14 } 15 for (int i = start; i < len; i++) { 16 if (!Character.isDigit(str.charAt(i))) 17 return (int) sum * sign; 18 sum = sum * 10 + str.charAt(i) - '0'; 19 if (sign == 1 && sum > Integer.MAX_VALUE) 20 return Integer.MAX_VALUE; 21 if (sign == -1 && (-1) * sum < Integer.MIN_VALUE) 22 return Integer.MIN_VALUE; 23 } 24 25 return (int) sum * sign; 26 }
1 public class StringtoInteger { 2 public int myAtoi(String input) { 3 char[] cha = input.toCharArray(); 4 int n = cha.length; 5 int i = 0; 6 int result = 0; 7 char sign = '+'; 8 char tmp; 9 while(i < n && cha[i] == ' '){ 10 i++; 11 } 12 if(i == n){return 0;} 13 if(i < n && (cha[i] == '+' || cha[i] == '-')){ 14 sign = cha[i]; 15 i++; 16 } 17 18 if(i == n){return 0;} 19 while(i < n && cha[i] >= '0' && cha[i] <= '9'){ 20 21 22 if(sign == '+') { 23 result = result*10+ Integer.valueOf(String.valueOf(cha[i])); 24 if(result % 10 != Integer.valueOf(String.valueOf(cha[i]))){ 25 return Integer.MAX_VALUE; 26 } 27 }else { 28 result = result*10 - Integer.valueOf(String.valueOf(cha[i])); 29 if(result % 10 != -Integer.valueOf(String.valueOf(cha[i]))){ 30 return Integer.MIN_VALUE; 31 } 32 } 33 i++; 34 } 35 return result; 36 } 37 public static void main(String[] args) { 38 String a = "2147483648"; 39 int b = new StringtoInteger().myAtoi(a); 40 System.out.println(b); 41 } 42 }
6. ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R 思路:1.编程语言中重视单个变化发现规律,最好不要使用数学统一规律解题,建议1~n的递增式寻找规律;2.sb[i] = new StringBuffer();//非标准型,需要进行实例化;3.由上至下再由下至上式存储。
1 package LeetCode; 2 3 /** 4 * Created by BlueMond on 2017/11/2. 5 */ 6 public class ZigZagConversion { 7 8 public String firstPart(String input, int nums){ 9 10 int n = input.length(); 11 char[] ch = new char[n]; 12 StringBuffer[] sb = new StringBuffer[nums]; 13 int k = 0; 14 15 for(int i = 0; i < n; i++){ 16 ch[i] = input.charAt(i); 17 }//可替换为 input.toCharArray() 18 for(int i = 0; i < nums; i++){ 19 sb[i] = new StringBuffer();//非标准型,需要进行实例化 20 } 21 while (k < n){ 22 for(int j = 0; j < nums && k < n; j++){ 23 sb[j].append(ch[k]); 24 k++; 25 } 26 for(int j = nums - 2; j > 0 && k < n; j--){ 27 sb[j].append(ch[k]); 28 k++; 29 } 30 } 31 for(int i = 1; i < nums; i++){ 32 sb[0].append(sb[i]); 33 } 34 return sb[0].toString(); 35 36 } 37 38 public static void main(String[] args){ 39 String input = "PAYPALISHIRING"; 40 String output = new ZigZagConversion().firstPart(input, 3); 41 System.out.println(output); 42 } 43 }
5. Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. 思路:使用中间轴向左向右延伸法,储存最长对称字符串;注意:判断条件是有序的,能够解决边界特殊指问题。?有序吗
1 package LeetCode; 2 3 /** 4 * Created by BlueMond on 2017/10/31. 5 */ 6 public class LongestPalindromicSubstring { 7 private int low = 0; 8 private int maxLen = 0; 9 10 public String firstPart(String input){ 11 int n = input.length() - 1; 12 if(n <= 0){ 13 return input; 14 } 15 for(int i = 0; i < n; i++){ 16 secondPart(input, i, i); 17 secondPart(input, i, i + 1); 18 } 19 return input.substring(low, low + maxLen); 20 } 21 22 public void secondPart(String input, int k, int j){ 23 while(k >= 0 && j < input.length() && input.charAt(k) == input.charAt(j)){ //有序!!!!! 24 25 k--; 26 j++; 27 28 } 29 if(maxLen < j - k - 1){ 30 maxLen = j - k - 1; //因为while循环内部多加并且多减了一次! 31 low = k + 1; 32 } 33 } 34 public static void main(String[] args){ 35 String input = "babafdgds"; 36 String output = new LongestPalindromicSubstring().firstPart(input); 37 System.out.print(output); 38 } 39 }
3.Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. Examples: Given "abcabcbb", the answer is "abc", which the length is 3. Given "bbbbb", the answer is "b", with the length of 1. Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring. 思路: HashMap实时存储单个字符,利用HashMap的键唯一性,对每次查询的内容进行定位,角标和定位角标(重复字符角标)相减得到最大MAX。
1 package leetCode; 2 import java.util.HashMap; 3 4 public class LongestSubstring { 5 public int firstPart(String input) { 6 HashMap<Character, Integer> hashString = new HashMap<>(); 7 int j = -1; 8 int max = 0; 9 10 for(int i = 0; i < input.length(); i++) { 11 if(hashString.containsKey(input.charAt(i))) { 12 // j = hashString.get(input.charAt(i)); 不同字符时可能会跳回到之前的点,导致max计算时添加更多的已重复字符串 13 j = Math.max(j, hashString.get(input.charAt(i))); 14 15 } 16 hashString.put(input.charAt(i), i); 17 max = Math.max(max, i - j); 18 // System.out.println(max + " i: " + i +" J: " +j); 19 } 20 21 return max; 22 } 23 24 public static void main(String[] args) { 25 String input = "abcabcdeab"; 26 int output = new LongestSubstring().firstPart(input); 27 System.out.println(output); 28 } 29 }
2. Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8
思路:listnode的生成方法,用t1指向l1的对象,替代t1进行l1的拓展;注意t1.next的声明问题;使用sum进行进位操作。
1 package LeetCode; 2 3 import org.omg.Messaging.SYNC_WITH_TRANSPORT; 4 5 /** 6 * Created by BlueMond on 2017/10/27. 7 */ 8 class ListNode { 9 int val; 10 ListNode next; 11 ListNode(int x) { val = x; } 12 } 13 public class AddTwoNumbers { 14 public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 15 16 ListNode t1 = l1; 17 ListNode t2 = l2; 18 ListNode l3 = new ListNode(0); 19 ListNode t3 = l3; 20 int sum = 0; 21 22 while (t1 != null || t2 != null){ 23 sum /= 10; 24 if(t1 != null){ 25 sum += t1.val; 26 t1 = t1.next; 27 } 28 if(t2 != null){ 29 sum += t2.val; 30 t2 = t2.next; 31 } 32 t3.next = new ListNode(sum % 10); 33 t3 = t3.next; 34 } 35 if(sum % 10 == 1){ 36 t3 = new ListNode(sum % 10); 37 } 38 39 return l3.next; 40 41 } 42 43 public static void main(String[] args) { 44 ListNode l1 = new ListNode(0); 45 ListNode d = l1; 46 d.next = new ListNode(4); 47 // System.out.println(l1.val + " " + l1.next.val + " " + l1.next.next.val); 48 ListNode l2 = new ListNode(5); 49 ListNode d2 = l2; 50 d2.next = new ListNode(6); 51 d2 = d2.next; 52 d2.next = new ListNode(4); 53 54 // System.out.println(l2.val + " " + l2.next.val + " " + l2.next.next.val); 55 56 57 ListNode output = new AddTwoNumbers().addTwoNumbers(l1, l2); 58 System.out.println("output:" + output.val + " " + output.next.val + " " + output.next.next.val); 59 } 60 }