diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..816a796 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +GenerateCodeTable.class diff --git a/GenerateCodeTable.class b/GenerateCodeTable.class deleted file mode 100644 index da90633..0000000 Binary files a/GenerateCodeTable.class and /dev/null differ diff --git a/GenerateCodeTable.java b/GenerateCodeTable.java index d89f687..abfd985 100644 --- a/GenerateCodeTable.java +++ b/GenerateCodeTable.java @@ -1,113 +1,211 @@ -import java.io.*; -/* -Used to generate table of contents. -1. No args: generate GitHub table -2. args == 'word', generate WordPress table. -3. args == 'all', genereate both table -*/ -public class GenerateCodeTable { - public static void main(String[] args) { - //Read Java Solution Folder - File folder = new File("./Java");//"." = current path - if (!folder.exists() || !folder.isDirectory()) { - System.out.println("Check Directory:1"); - return; - } - File[] listOfFiles = folder.listFiles(); - if (listOfFiles == null) { - System.out.println("Check Directory:2"); - return; - } - - String outputContent = ""; - File outFile; - - if (args.length == 0){ - outputContent = generateREADME(listOfFiles); - printTable("README.md", outputContent); - } else if (args != null && args[0].contains("word")) {//Wordpress - outputContent = generateWordPressPage(listOfFiles); - printTable("WordPress.txt", outputContent); - } else if (args != null && args[0].contains("all")) { - outputContent = generateREADME(listOfFiles); - printTable("README.md", outputContent); - outputContent = generateWordPressPage(listOfFiles); - printTable("WordPress.txt", outputContent); - } else { - return; - } - - - } - - public static String generateWordPressPage(File[] listOfFiles) { - //Assemble output - String outputContent = "Java Solutions to problems from LintCode(http://LintCode.com).\n" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - ""; - - int count = 0; - for (File file : listOfFiles) { - if (file.getName().contains(".java")) { - //outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/shawnfan/LintCode/blob/master/Java/"+ file.getName() +")| |" + "Java|\n"; - outputContent+= - "" + - "" + - "" + - "" + - "" + - ""; - count++; - } - } - - outputContent += "
#Problem      Level  Language
" + count + "" + file.getName() + "Java
"; - return outputContent; - } - - - /* - Generate GitHub ReadMe file - */ - public static String generateREADME(File[] listOfFiles) { - //Assemble output - String outputContent = "# LintCode\n\n" + - "To host Java Solutions to problems from LintCode(http://LintCode.com).\n" + - "I Will try to revise the solutions once new problem or new testing case occurs.\n\n" + - "| Squence | Problem | Level | Language |\n" + - "|:-------:|:--------------|:---------------|:---------:|\n"; - int count = 0; - for (File file : listOfFiles) { - if (file.getName().contains(".java")) { - outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/shawnfan/LintCode/blob/master/Java/"+ file.getName() +")| |" + "Java|\n"; - count++; - } - } - return outputContent; - } - - public static void printTable(String fileName, String outputContent) { - System.out.println(outputContent); - //Write to README.md - try { - File outFile = new File(fileName); - FileOutputStream fop = new FileOutputStream(outFile); - byte[] contentInBytes = outputContent.getBytes(); - fop.write(contentInBytes); - fop.flush(); - fop.close(); - System.out.println("Mission Accomplished. Now go ahead and commit"); - } catch (IOException e) { - e.printStackTrace(); - } - } - +import java.io.*; +/* +Used to generate table of contents. + - No args: generate GitHub table + - args == 'wordpress', generate WordPress table. + - args == 'review', generate Review Page + - args == 'all', genereate both table +*/ +public class GenerateCodeTable { + public final static String TUTORIAL_KEY_WORD = "tutorial:"; + public static void main(String[] args) { + //Read Java Solution Folder + File folder = new File("./Java");//"." = current path + if (!folder.exists() || !folder.isDirectory()) { + System.out.println("Check Directory:1"); + return; + } + File[] listOfFiles = folder.listFiles(); + if (listOfFiles == null) { + System.out.println("Check Directory:2"); + return; + } + + String outputContent = ""; + File outFile; + + if (args.length == 0){ + outputContent = generateREADME(listOfFiles); + printTable("README.md", outputContent); + } else if (args != null && args[0].contains("wordpress")) {//Wordpress + outputContent = generateWordPressPage(listOfFiles); + printTable("WordPress.txt", outputContent); + } else if (args != null && args[0].contains("review")) {//Review Page + outputContent = generateReviewPage(listOfFiles); + printTable("ReviewPage.md", outputContent); + } else if (args != null && args[0].contains("all")) { + outputContent = generateREADME(listOfFiles); + printTable("README.md", outputContent); + outputContent = generateWordPressPage(listOfFiles); + printTable("WordPress.txt", outputContent); + outputContent = generateReviewPage(listOfFiles); + printTable("ReviewPage.md", outputContent); + } else { + return; + } + } + + /* + Output the content into file + */ + public static void printTable(String fileName, String outputContent) { + System.out.println(outputContent); + //Write to README.md + try { + File outFile = new File(fileName); + FileOutputStream fop = new FileOutputStream(outFile); + byte[] contentInBytes = outputContent.getBytes(); + fop.write(contentInBytes); + fop.flush(); + fop.close(); + System.out.println("Mission Accomplished. Now go ahead and commit"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /* + Generate Wordpress contents + */ + public static String generateWordPressPage(File[] listOfFiles) { + //Assemble output + String outputContent = "Java Solutions to algorithm problems from LintCode, LeetCode...etc.\n" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + int count = 0; + for (File file : listOfFiles) { + if (file.getName().contains(".java")) { + //outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/awangdev/LintCode/blob/master/Java/"+ file.getName() +")| |" + "Java|\n"; + outputContent+= + "" + + "" + + "" + + "" + + "" + + ""; + count++; + } + } + + outputContent += "
#Problem Level Language
" + count + "" + file.getName() + "Java
"; + return outputContent; + } + + + /* + Generate GitHub ReadMe contents + */ + public static String generateREADME(File[] listOfFiles) { + //Assemble output + String outputContent = "# Java Algorithm Problems\n\n" + + "### 前戏\n" + + "To host Java Solutions to algorithm problems from LintCode, LeetCode...etc.\n" + + "I Will try to revise the solutions once new problem or new testing case occurs.\n" + + "**Mid 2016** I realize that people may want to contribute to this repo, and make it better by contributing fixes, better solutions ... etc. Free free to send pull request. Once verified, I'm happy to merge in!\n" + + "CALM DOWN AND CODE ON! Fellows! \n\n" + + "### News\n" + + "2017年1月17日, 陪我征战多年的 2014 MackBookPro i7 3.xGHz 被一杯清水结束了生命,在这里深切缅怀悼念。这个Git Repo是小M陪我一字一句打出来的,有过蹉跎,也有过辉煌,陪我从Day1刷题一直刷到了Day1之中。直至今日,小M记录的代码还在给广大coder带来福利。为了延续小M无私奉献的精神,我将重新在这个repo活跃起来,重整已有的问题,也会尝试总结一些System Design方面的想法,将小M还没有能够达成的梦想实现。\n\n" + + "| Squence | Problem | Level | Language | Video Tutorial|\n" + + "|:-------:|:--------------|:------:|:---------:|:-------------:|\n"; + int count = 0; + for (File file : listOfFiles) { + String tutorialLink = ""; + String calculatedLevel = ""; + if (file.getName().contains(".java")) { + try { + final BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream("Java/" + file.getName()), "UTF-8")); + final String levelLine = reader.readLine().trim(); + if (levelLine.length() == 1) { + calculatedLevel = calculateLevel(levelLine.toUpperCase()); + } + final String tutorialLine = reader.readLine(); + if (tutorialLine.indexOf(TUTORIAL_KEY_WORD) == 0) { + tutorialLink = "[Link](" + tutorialLine.substring(TUTORIAL_KEY_WORD.length()) + ")"; + } + } catch (Exception e) { + System.err.format("IOException: %s%n", e); + } + String convertedFileName = file.getName().replace(" ", "%20"); + outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/awangdev/LintCode/blob/master/Java/" + + convertedFileName + ")|" + calculatedLevel + "|" + "Java|" + tutorialLink + "|\n"; + count++; + } + } + return outputContent; + } + + + /* + Generate Review Page contents + Review Page content: + 1. Sequence + 2. Name + 3. Difficulty + 4. Summary of solution, key points. + */ + public static String generateReviewPage(File[] listOfFiles) { + //Assemble output + String outputContent = "# Review Page\n\n" + + "This page summarize the solutions of all problems. For thoughts,ideas written in English, refer to deach individual solution. \n" + + "New problems will be automatically updated once added.\n\n"; + + int count = 0; + for (File file : listOfFiles) { + if (file.getName().contains(".java")) { + String convertedFileName = file.getName().replace(" ", "%20"); + outputContent += "**" + count + ". [" + file.getName() + "](https://github.com/awangdev/LintCode/blob/master/Java/"+ convertedFileName +")**"; + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("Java/" + file.getName()), "UTF-8")); + String line = null; + int countLine = 0; + while ((line = reader.readLine()) != null && !line.equals("```")) { + if (countLine == 0) { + final String trimedLine = line.trim().toUpperCase(); + if (trimedLine.length() == 1 && !calculateLevel(trimedLine).isEmpty()) { + outputContent += " Level: " + calculateLevel(trimedLine) + "\n"; + } else { + outputContent += "\n"; + } + } else if (countLine == 1 && line.indexOf(TUTORIAL_KEY_WORD) == 0) { + outputContent += " [Tutorial Link](" + line.substring(TUTORIAL_KEY_WORD.length()) + ")\n"; + } else { + outputContent += line + "\n"; + } + countLine++; + } + } catch (Exception e) { + System.err.format("IOException: %s%n", e); + }//end of one file + outputContent += "\n---\n"; + count++; + } + } + return outputContent; + } + + private static String calculateLevel(final String level) { + switch(level) { + case "N" : + return "Naive"; + case "E" : + return "Easy"; + case "M" : + return "Medium"; + case "H" : + return "Hard"; + case "S" : + return "Super"; + } + return ""; + } } \ No newline at end of file diff --git a/Java/2 Sum II - Input array is sorted.java b/Java/2 Sum II - Input array is sorted.java new file mode 100755 index 0000000..72327c8 --- /dev/null +++ b/Java/2 Sum II - Input array is sorted.java @@ -0,0 +1,57 @@ +M + +排序好的array. Binary Search移动start和end,核查sum。 + + +``` +/* +Given an array of integers that is already sorted in ascending order, +find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, +where index1 must be less than index2. +Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 + +Tags: Array Two Pointers, Binary Search +Similar Problems: (M) Two Sum + +*/ + + +/* +Thoughts: +Do a binary search, but do not over-complicate it: +Start, end. Check if nums[start] + nums[end] == target. +binary move it: in fact, moving the two border, 1 position at a time +*/ + +public class Solution { + public int[] twoSum(int[] nums, int target) { + int[] rst = new int[2]; + if (nums == null || nums.length <= 1) { + return rst; + } + int start = 0; + int end = nums.length - 1; + while(start < end) { + long sum = (long)(nums[start] + nums[end]); + if (target == sum) { + rst[0] = start + 1; + rst[1] = end + 1; + break; + } else if (target > sum) { + start++; + } else { + end--; + } + }//END while + return rst; + } +} + +``` \ No newline at end of file diff --git a/Java/2 Sum II.java b/Java/2 Sum II.java new file mode 100755 index 0000000..0db648d --- /dev/null +++ b/Java/2 Sum II.java @@ -0,0 +1,122 @@ +M + +LintCode的题. 注意找的是greater/bigger than target。 + +由于给定条件允许O(nLogn): + sort + two pointer + +while里面two pointer移动。每次如果num[left]+num[right] > target,那么其中所有num[left++]的加上num[right]都>target. +也就是,num[right]不动,计算加入挪动left能有多少组,那就是: right-left这么多。 全部加到count上去。 +然后right--.换个right去和前面的left部分作比较。 + +``` +/* +Given an array of integers, find how many pairs in the array such that +their sum is bigger than a specific target number. Please return the number of pairs. +Example +numbers=[2, 7, 11, 15], target=24 + +return 1 + +Challenge +Either of the following solutions are acceptable: + +O(1) Space, O(nlogn) Time +Tags Expand +Two Pointers + +*/ + +/* +Thoughts: +After doing Trigle Count...Can we just do the same for this, move while pointers to center? +OMG. The original idea was sooooooo complicated. +*/ +public class Solution { + public int twoSum2(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return 0; + } + int count = 0; + int left = 0; + int right = nums.length - 1; + Arrays.sort(nums); + while (left < right) { + if (nums[left] + nums[right] > target) { + count += (right - left); + right--; + } else { + left++; + } + } + return count; + } +} + +//Below are bad solutions. Don't worry about them + +/* + +Thoughts: +1. For loop to try each element from (i ~ end). O(n) +2. In for, do binary search on nums[i] + nums[j] > target, +3. count += (length - j) + +Note: when not found, return nums.length, because at then end, (length - length) == 0, which will be added to count. +Note: Always pin target down, and move mid to compare. Don't get confused +Also, take care of corner cases. +*/ + +public class Solution { + public int twoSum2(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return 0; + } + int count = 0; + Arrays.sort(nums); + for (int i = 1; i < nums.length; i++) { + int index = binarySearch(nums, target - nums[i - 1], i, nums.length - 1); + count += nums.length - index; + } + return count; + } + + public int binarySearch(int[] nums, int target, int start, int end) { + int mid; + int sum; + while (start + 1 < end) { + mid = start + (end - start) /2; + if (mid - 1 >= 0 && nums[mid-1] <= target && target < nums[mid]) { + return mid; + } else if (mid + 1 < nums.length && nums[mid] <= target && target < nums[mid + 1]) { + return mid + 1; + } else if (target < nums[mid]) { + end = mid; + } else { + start = mid; + } + } + if (nums[start] > target) { + return start; + } + return (nums[end] > target) ? end : nums.length; + } +} + +//Brutle force, O(n^2) +public class Solution { + public int twoSum2(int[] nums, int target) { + if (nums == null || nums.length == 0) { + return 0; + } + int count = 0; + for (int i = 0; i < nums.length - 1; i++) { + for (int j = i + 1; j < nums.length; j++) { + count += (nums[i] + nums[j] > target) ? 1 : 0; + } + } + } +} + +``` \ No newline at end of file diff --git a/Java/2 Sum.java b/Java/2 Sum.java old mode 100644 new mode 100755 index 06fea20..1ddbd01 --- a/Java/2 Sum.java +++ b/Java/2 Sum.java @@ -1,62 +1,129 @@ -/* -Given an array of integers, find two numbers such that they add up to a specific target number. - -The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. - -Note -You may assume that each input would have exactly one solution - -Example -numbers=[2, 7, 11, 15], target=9 - -return [1, 2] - -Challenge -1. O(1) Space, O(nlogn) Time - -2. O(n) Space, O(n) Time - -Tags Expand -Array Two Pointers - - -Using a HashMap, O(n) space and O(n) time. -Thinking process: -Push everything into a HashMap. -Check if one element exist in the HashMap, if so save it. Meanwhile, save the other one. -Trick: after adding into the HashMap, we are looking for the 2nd index first. This is particularly because the way we write the code in optimized form: - always check (target - current) from the HashMap. If exist, that means index0 has already been pushed into the HashMap and current value is at index1. -(key, value) = (numbers[i], i) -Note: return index+1 because this is not 0-based. -*/ - -public class Solution { - /* - * @param numbers : An array of Integer - * @param target : target = numbers[index1] + numbers[index2] - * @return : [index1 + 1, index2 + 1] (index1 < index2) - */ - //Using HashMap - public int[] twoSum(int[] numbers, int target) { - if (numbers == null || numbers.length == 0) { - return null; - } - int[] rst = new int[2]; - HashMap map = new HashMap(); - for (int i = 0; i < numbers.length; i++) { - if (map.containsKey(target - numbers[i])) { - rst[0] = map.get(target - numbers[i]) + 1; - rst[1] = i + 1; - } else { - map.put(numbers[i], i); - } - } - return rst; - } -} - - - -//2. O(1) Space O(nlogn) time -//TODO - +M +tutorial:https://www.youtube.com/watch?v=P8zBxoVY1oI&feature=youtu.be + +解法1:相对暴力简洁, HashMap,找到一个value, 存一个; 若在HashMap里面 match 到结果, 就return HashMap里存的index. O(n) space && time. + +解法2:Sort array, two pointer 前后++,--搜索。Sort 用时O(nlogn). +1. 第一步 two pointer 找 value. +2. 注意,要利用额外的空间保留original array, 用来时候找index. (此处不能用HashMap,因为以value 为key,但value可能重复) +O(n) space, O(nlogn) time. + + +``` + +/* +Given an array of integers, find two numbers such that they add up to a specific target number. +The function twoSum should return indices of the two numbers such that they add up to the target, +where index1 must be less than index2. +Please note that your returned answers (both index1 and index2) are NOT zero-based. +Example +numbers=[2, 7, 11, 15], target=9 +return [1, 2] +Note +You may assume that each input would have exactly one solution +Challenge +Either of the following solutions are acceptable: +O(n) Space, O(nlogn) Time +O(n) Space, O(n) Time +Tags Expand +Two Pointers Sort Hash Table Array Airbnb Facebook +*/ + +/* +Thoughts: + Using a HashMap, O(n) space and O(n) time. + Thinking process: + Push everything into a HashMap. + Check if one element exist in the HashMap, if so save it. Meanwhile, save the other one. + Trick: after adding into the HashMap, we are looking for the 2nd index first. + Always check (target - current) from the HashMap. + If exist, that means index0 has already been pushed into the HashMap and current value is at index1. + (key, value) = (numbers[i], i) + Note: return index+1 because this is not 0-based. +*/ + +public class Solution { + //Using HashMap + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length == 0) { + return null; + } + int[] rst = new int[2]; + HashMap map = new HashMap(); + for (int i = 0; i < numbers.length; i++) { + if (map.containsKey(target - numbers[i])) { + rst[0] = map.get(target - numbers[i]) + 1; + rst[1] = i + 1; + break; + } else { + map.put(numbers[i], i); + } + } + return rst; + } +} + + + +//2. O(n) Space O(nlogn) time +/* + Feels like binary search when looking at O(nlogn) + 1. sort + 2. loop all number + 3. binary search on rest +*/ +public class Solution { + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length == 0) { + return null; + } + int[] original = new int[numbers.length]; + for (int i = 0; i < numbers.length; i++) { + original[i] = numbers[i]; + } + + Arrays.sort(numbers); + int start = 0; + int end = numbers.length - 1; + int num1 = -1; + int num2 = -1; + while (start != end) { + int sum = numbers[start] + numbers[end]; + if (sum == target) { + num1 = numbers[start]; + num2 = numbers[end]; + break; + }else if (sum < target) { + start++; + } else { + end--; + } + } + + //Find the num1,num2 in original array and record the index + int[] rst = new int[2]; + rst[0] = -1; + rst[1] = -1; + for (int i = 0; i < original.length; i++) { + if (original[i] == num1 || original[i] == num2) { + if (rst[0] == -1) { + rst[0] = i + 1; + } else { + rst[1] = i + 1; + break; + } + } + } + return rst; + } +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Java/3 Sum Closest.java b/Java/3 Sum Closest.java index ea4b234..da399e9 100644 --- a/Java/3 Sum Closest.java +++ b/Java/3 Sum Closest.java @@ -1,28 +1,33 @@ +M + +3Sum 的一种简单形式, 并且都没有找index, value, 而只是找个sum罢了. + +double for loop。 2Sum只能用土办法 left/right 2 pointers。 O(n^2) + +注意:check closest时候用long, 以免int不够用 + +``` /* Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. - Note You may assume that each input would have exactly one solution. - Example For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). - Tags Expand Two Pointers Sort Array -Thinking process: -Similar to 3 SUM. -Starting from the left-element, assume it's the solution. Move the 2 pointers in the right-side-array. -Using the two pointers, trying to find ele1 + ele2 + ele3 = closest number to target. -Note: for comparing closet, use initial value Integer.MAX_VALUE. Be aware of the overflow of integer, use long to handle. */ +/* +Thoughts: + Similar to 3 SUM. + Starting from the left-element, assume it's the solution. Move the 2 pointers in the right-side-array. + Using the two pointers, trying to find ele1 + ele2 + ele3 = closest number to target. + Note: for comparing closet, use initial value Integer.MAX_VALUE. Be aware of the overflow of integer, use long to handle. + +*/ public class Solution { - /** - * @param numbers: Give an array numbers of n integer - * @param target : An integer - * @return : return the sum of the three integers, the sum closest target. - */ + public int threeSumClosest(int[] num, int target) { if (num == null || num.length < 3) { return Integer.MAX_VALUE; @@ -49,3 +54,4 @@ public int threeSumClosest(int[] num, int target) { } } +``` \ No newline at end of file diff --git a/Java/3 Sum Smaller.java b/Java/3 Sum Smaller.java new file mode 100644 index 0000000..55642b1 --- /dev/null +++ b/Java/3 Sum Smaller.java @@ -0,0 +1,58 @@ +一般的O(n3)肯定不行。在此基础上优化。 +发现j,k满足条件时候,(k - j)就是所有 sum target, 又因为j不能后退,只能k--,那么问题就被锁定了. 这样可以做到O(n2) +``` +/* +Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target. + +For example, given nums = [-2, 0, 1, 3], and target = 2. + +Return 2. Because there are two triplets which sums are less than 2: + +[-2, 0, 1] +[-2, 0, 3] + +Follow up: +Could you solve it in O(n2) runtime? + +Tags: Array Two Pointers +Similar Problems:(M) 3Sum, (M) 3Sum Closest + +*/ + + +/* +Thoughts: +Similar to 3 sum, but ofcourse, this one check on '<' so we can not use HashMap anymore. +Basic concept is to fix first number, then check for the rest two numbers, see if they addup < target. +When checking j and k, realize something nice: + if nums[j] + nums[k] < target - nums[i], that means for all index <= k will work, so directly add (k - j) to result (that's: index = j+1, j+2, ....,k) + also, move j forward for next round. +OR, if three-add-up >= target, since j can only increase, we do k-- to make the three-add-up smaller + +Note: +Don't forget to sort, otherwise the sequence/order is unpredictable +*/ +public class Solution { + public int threeSumSmaller(int[] nums, int target) { + if (nums == null || nums.length <= 2) { + return 0; + } + Arrays.sort(nums); + int rst = 0; + for (int i = 0; i < nums.length - 2; i++) { + int j = i + 1; + int k = nums.length - 1; + while (j < k) { + if (nums[i] + nums[j] + nums[k] >= target) { + k--; + } else { + rst += (k - j); + j++; + } + } + }//END for + return rst; + } +} +``` \ No newline at end of file diff --git a/Java/3 Sum.java b/Java/3 Sum.java index df0a63e..e84bc84 100644 --- a/Java/3 Sum.java +++ b/Java/3 Sum.java @@ -1,44 +1,61 @@ -/* -Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. +M -Note -Elements in a triplet (a,b,c) must be in non-descending order. (ie, a = b = c) +用个for loop 加上 2sum 的土办法。 -The solution set must not contain duplicate triplets. +注意: + 1. 找 value triplets, 多个结果。注意,并非找index。 + 2. 要升序, 第一层for loop 从最后一个元素挑起, 保证了顺序。 + 3. 去掉duplicate: check用过的同样的数字,都跳掉。不需要用同样的数字再计算一边已有结果。 + +步骤: + 1. For loop 挑个数字A. + 2. 2Sum 出一堆2个数字的结果 + 3. Cross match 步骤1里面的A. + +时间 O(n^2), 两个nested loop + + +另外, 还是可以用HashMap来做2Sum。稍微短点。还是要注意handle duplicates. + +再另外(leetcode做时写的):先sort,然后two pointer。 + +``` +/* +Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? +Find all unique triplets in the array which gives the sum of zero. Example For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) - (-1, -1, 2) +Note +Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c) + +The solution set must not contain duplicate triplets. Tags Expand -Two Pointers Sort Array - -Thinking process: -Cannot use HashMap for this problem because of the duplicates. See the bottom of this file for the failed version. -Remember to check for null and edge-soluton. -Before everything, Arrays.sort() the given array, in order to effectively handle the duplicates. -At 3SUM level, takes 1 element out and do 2SUM on the rest of the front elements of the array. Note, 2SUM has multitple solutions (need to handle duplicates) -Cross-match the 2SUM solution with the selected element from 3SUM level. +Two Pointers Sort Array Facebook */ +/* +Thoughts: + Remember to check for null and edge-soluton. + Before everything, Arrays.sort() the given array, in order to effectively handle the duplicates. + At 3SUM level, takes 1 element out and do 2SUM on the rest of the front elements of the array. Note, 2SUM has multitple solutions (need to handle duplicates) + Cross-match the 2SUM solution with the selected element from 3SUM level. +*/ public class Solution { - /** - * @param numbers : Give an array numbers of n integer - * @return : Find all unique triplets in the array which gives the sum of zero. - */ public ArrayList> threeSum(int[] numbers) { ArrayList> rst = new ArrayList>(); if (numbers == null && numbers.length <= 2) {// Length at least >= 3 return rst; } Arrays.sort(numbers);//Sort in order to handle duplicates - for (int i = numbers.length - 1; i >= 2; i--) {// i >=2 because at least 3 element in result. + for (int i = numbers.length - 1; i >= 2; i--) {// i >=2 because at least 3 element in result; starting from end, ensures non-descending order if (i < numbers.length - 1 && numbers[i] == numbers[i + 1]) { - continue;//The case of numbers[i + 1] should have already covered all possibilities of the case numbers[i], so safe to skip + continue;//The case of numbers[i + 1]: should have already covered all possibilities of the case numbers[i], so safe to skip } ArrayList> twoSum = calTwoSum(numbers, i - 1, 0 - numbers[i]);//Pick the 3rd element numbers[i] for (int j = 0; j < twoSum.size(); j++) {//Find two sum of rest-front elements. Cross add them with numbers[i] @@ -51,9 +68,6 @@ public ArrayList> threeSum(int[] numbers) { //Two Sum. Multiple answer public ArrayList> calTwoSum(int[] num, int end, int target) { ArrayList> rst = new ArrayList>(); - if (num == null || num.length <= 1) {//Length at least >= 2 - return rst; - } int left = 0; int right = end; while (left < right) { @@ -83,42 +97,118 @@ public ArrayList> calTwoSum(int[] num, int end, int target) { } - - - +/* + Thoughts: + Exact same approach, except using HashMap in 2Sum +*/ +//With HashMap 2Sum +public class Solution { + public ArrayList> threeSum(int[] numbers) { + ArrayList> rst = new ArrayList>(); + if (numbers == null && numbers.length <= 2) {// Length at least >= 3 + return rst; + } + Arrays.sort(numbers);//Sort in order to handle duplicates + for (int i = numbers.length - 1; i >= 2; i--) {// i >=2 because at least 3 element in result; starting from end, ensures non-descending order + if (i < numbers.length - 1 && numbers[i] == numbers[i + 1]) { + continue;//The case of numbers[i + 1]: should have already covered all possibilities of the case numbers[i], so safe to skip + } + ArrayList> twoSum = calTwoSum(numbers, i - 1, 0 - numbers[i]);//Pick the 3rd element numbers[i] + for (int j = 0; j < twoSum.size(); j++) {//Find two sum of rest-front elements. Cross add them with numbers[i] + twoSum.get(j).add(numbers[i]); + } + rst.addAll(twoSum); + } + return rst; + } + //Two Sum. Multiple answer, with HashMap + public ArrayList> calTwoSum(int[] num, int end, int target) { + ArrayList> rst = new ArrayList>(); + ArrayList match; + HashMap map = new HashMap(); + for (int i = 0; i <= end; i++) { + if (map.containsKey(num[i])) { + match = new ArrayList(); + match.add(num[map.get(num[i])]); + match.add(num[i]); + if (!rst.contains(match)) { + rst.add(new ArrayList(match)); + } + } else { + map.put(target - num[i], i); + } + //Skip duplicate + if (i < end && num[i] == num[i + 1]) { + continue; + } + } + return rst; + } +} /* -The following is a exceeding time version. -I believe the concept is clear, but it does not handle duplicates well. So we can't use this version. + From LeetCode Solution + Thoughts: + sort list. O(nLogn) + end: n^2 + for (i = 0 ~ n) { + int target = 0 - nums[i]; + while (start + 1 < end) { + start + end == target { + rst.add(i, star, end); + keep looking: start ++, end-- + } + else start + end < target? + start++ + else + end--; + } + } + } +Note: + Check duplicates. Compute a unique string to savei set +*/ public class Solution { - public ArrayList> threeSum(int[] numbers) { - ArrayList> rst = new ArrayList>(); - if (numbers.length <= 2) { + public List> threeSum(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { return rst; } - Arrays.sort(numbers); - for (int i = 0; i < numbers.length; i++){ - HashMap map = new HashMap(); - for (int j = i; j < numbers.length; j++) { - int remain = 0 - numbers[i] - numbers[j]; - if (map.containsKey(remain) && map.get(remain) != i) { - ArrayList list = new ArrayList(); - list.add(numbers[i]); - list.add(remain); - list.add(numbers[j]); - if (!rst.contains(list)){ - rst.add(list); - } + + Arrays.sort(nums); + HashSet set = new HashSet(); + //use old target to check duplicates. instead of set. + for (int i = 0; i < nums.length - 2; i++) { + int target = 0 - nums[i]; + int start = i + 1; + int end = nums.length - 1; + + ArrayList list = new ArrayList(); + while (start < end) { + if (nums[start] + nums[end] == target && + !set.contains(nums[i] + "," + nums[start] + "," + nums[end])) { + list.add(nums[i]); + list.add(nums[start]); + list.add(nums[end]); + rst.add(list); + set.add(nums[i] + "," + nums[start] + "," + nums[end]); + list = new ArrayList(); + start++; + end--; + } else if (nums[start] + nums[end] < target) { + start++; } else { - map.put(numbers[j], j); + end--; } - } + }//end while } + return rst; } } -*/ \ No newline at end of file + +``` \ No newline at end of file diff --git a/Java/4 Sum.java b/Java/4 Sum.java old mode 100644 new mode 100755 index 7426ba2..f8fee31 --- a/Java/4 Sum.java +++ b/Java/4 Sum.java @@ -1,81 +1,230 @@ -/* -Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. - -Example -For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: - -(-1, 0, 0, 1) - -(-2, -1, 1, 2) - -(-2, 0, 0, 2) - -Note -Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d) - -The solution set must not contain duplicate quadruplets. - -Tags Expand -Two Pointers Sort Hash Table Array - -Thinking process: -Perform another layer outsideo of 3SUM. - -Note: If try to divide and perform two 2SUM, it will be a bit difficult. Refer to http://blog.csdn.net/linhuanmars/article/details/24826871 -*/ - -public class Solution { - /** - * @param numbers : Give an array numbersbers of n integer - * @param target : you need to find four elements that's sum of target - * @return : Find all unique quadruplets in the array which gives the sum of - * zero. - */ - public ArrayList> fourSum(int[] numbers, int target) { - ArrayList> rst = new ArrayList>(); - if(numbers == null || numbers.length < 4) { - return rst; - } - Arrays.sort(numbers); - //Pick 1st element - for (int i = 0; i < numbers.length - 3; i++) { - if (i != 0 && numbers[i] == numbers[i - 1]) {//Check for duplicate of 1st element - continue; - } - //Pick 2nd element - for (int j = i + 1; j < numbers.length - 2; j++) { - if (j != i + 1 && numbers[j] == numbers[j - 1]) {//Check for duplicate of 2nd element - continue; - } - //Pick 3rd and 4th element - int third = j + 1; - int fourth = numbers.length - 1; - while (third < fourth) { - int sum = numbers[i] + numbers[j] + numbers[third] + numbers[fourth]; - if (sum < target) { - third++; - } else if (sum > target) { - fourth--; - } else {//sum == target - ArrayList list = new ArrayList(); - list.add(numbers[i]); - list.add(numbers[j]); - list.add(numbers[third]); - list.add(numbers[fourth]); - rst.add(list); - third++; - fourth--; - while (third < fourth && numbers[third] == numbers[third - 1]) { - third++; - } - while (third < fourth && numbers[fourth] == numbers[fourth + 1]){ - fourth--; - } - } - } - } - } - return rst; - } -} - +M + +方法1: 3Sum外面再加一层. 参考3Sum. 时间O(n^3)。 但此方法在k-sum时候,无疑过于费时间. O(n^k) + +方法2: 参见 http://lifexplorer.me/leetcode-3sum-4sum-and-k-sum/ + 1. 利用2Sum的原理,把4Sum分为连个2Sum。左一个pair,右一个pair,每个pair里面放2个数字。 + 2. 以一个点,i,作为分界口,也要列举出所有i之前的pair,作为基础。 + 3. 再尝试从所有i+1后面,找合适的2nd pair。 + + 注意:在造class Pair时候,要做@override的function: hashCode(), equals(Object d). 平时不太想得起来用。 + +``` +/* +Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? + +Find all unique quadruplets in the array which gives the sum of target. + +Example +Given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: + +(-1, 0, 0, 1) +(-2, -1, 1, 2) +(-2, 0, 0, 2) +Note +Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d) +The solution set must not contain duplicate quadruplets. + +Tags Expand +Two Pointers Sort Hash Table Array + +*/ + +/* +Thoughts +Perform another layer outside of 3SUM. O(n^3). +Note: If try to divide and perform two 2SUM, it will be a bit difficult. Refer to http://blog.csdn.net/linhuanmars/article/details/24826871 + +*/ +public class Solution { + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if(numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + //Pick 1st element + for (int i = 0; i < numbers.length - 3; i++) { + if (i != 0 && numbers[i] == numbers[i - 1]) {//Check for duplicate of 1st element + continue; + } + //Pick 2nd element + for (int j = i + 1; j < numbers.length - 2; j++) { + if (j != i + 1 && numbers[j] == numbers[j - 1]) {//Check for duplicate of 2nd element + continue; + } + //Pick 3rd and 4th element + int third = j + 1; + int fourth = numbers.length - 1; + while (third < fourth) { + int sum = numbers[i] + numbers[j] + numbers[third] + numbers[fourth]; + if (sum < target) { + third++; + } else if (sum > target) { + fourth--; + } else {//sum == target + ArrayList list = new ArrayList(); + list.add(numbers[i]); + list.add(numbers[j]); + list.add(numbers[third]); + list.add(numbers[fourth]); + rst.add(list); + third++; + fourth--; + while (third < fourth && numbers[third] == numbers[third - 1]) { + third++; + } + while (third < fourth && numbers[fourth] == numbers[fourth + 1]){ + fourth--; + } + } + } + } + } + return rst; + } +} + + +/* +NOT Complete yet. Has a order issue in HashSet +http://lifexplorer.me/leetcode-3sum-4sum-and-k-sum/ +Thoughts: +Utilize 2Sum. + +*/ + +public class Solution { + //Create class Pair for HashSet to use + class Pair { + Integer x; + Integer y; + + public Pair(int x, int y){ + this.x = x; + this.y = y; + } + + @Override + public int hashCode(){ + return this.x.hashCode() + this.y.hashCode(); + } + + @Override + public boolean equals(Object d) { + if (!(d instanceof Pair)) { + return false; + } + Pair p = (Pair)d; + return (this.x == p.x) && (this.y == p.y); + } + } + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if (numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + HashMap> map = new HashMap>(); + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) { + int sum = numbers[i] + numbers[j]; + if (map.containsKey(target - sum)) { + for (Pair p : map.get(target - sum)) { + ArrayList list = new ArrayList(); + list.add(p.x); + list.add(p.y); + list.add(numbers[i]); + list.add(numbers[j]); + if (!rst.contains(list)) { + rst.add(list); + } + } + } + } + //Add all pairs up to i + for (int j = 0; j < i; j++) { + int sum = numbers[i] + numbers[j]; + if (!map.containsKey(sum)) { + map.put(sum, new HashSet()); + } + map.get(sum).add(new Pair(numbers[j], numbers[i])); + } + } + + return rst; + } + +} + + + +public class Solution { + //Create class Pair for HashSet to use + class Pair { + Integer x; + Integer y; + + public Pair(int x, int y){ + this.x = x; + this.y = y; + } + + @Override + public int hashCode(){ + return this.x.hashCode() + this.y.hashCode(); + } + + @Override + public boolean equals(Object d) { + if (!(d instanceof Pair)) { + return false; + } + Pair p = (Pair)d; + return (this.x == p.x) && (this.y == p.y); + } + } + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if (numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + HashMap> map = new HashMap>(); + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) { + int sum = numbers[i] + numbers[j]; + if (map.containsKey(target - sum)) { + for (Pair p : map.get(target - sum)) { + ArrayList list = new ArrayList(); + list.add(p.x); + list.add(p.y); + list.add(numbers[i]); + list.add(numbers[j]); + if (!rst.contains(list)) { + rst.add(list); + } + } + } + } + //Add all pairs up to i + for (int j = 0; j < i; j++) { + int sum = numbers[i] + numbers[j]; + if (!map.containsKey(sum)) { + map.put(sum, new ArrayList()); + } + map.get(sum).add(new Pair(numbers[j], numbers[i])); + } + } + + return rst; + } + +} + + + +``` \ No newline at end of file diff --git a/Java/A+B.java b/Java/A+B.java index 61eaebc..5607c11 100644 --- a/Java/A+B.java +++ b/Java/A+B.java @@ -1,30 +1,48 @@ -/* -For given numbers a and b in function aplusb, return the sum of them. +E -Note -You don't need to parse the input and output. Just calculate and return. +^ 是不完全加法. 每次都忽略了进位。而 & 刚好可以算出需要的所有进位。 + +那么就,首先记录好进位的数字:carry. 然后 a^b 不完全加法一次。然后b用来放剩下的carry, 每次移动一位,继续加,知道b循环为0为止。 + +Bit Operation +Steps: + a & b: 每bit可能出得余数 + a ^ b: 每bit在此次操作可能留下的值,XOR 操作 + 每次左移余数1位,然后存到b, 再去跟a做第一步。loop until b == 0 + +(http://www.meetqun.com/thread-6580-1-1.html) + +``` +/* +Write a function that add two numbers A and B. You should not use + or any arithmetic operators. Example -If a=1 and b=2 return 3 +Given a=1 and b=2 return 3 + +Note +There is no need to read data from standard input stream. Both parameters are given in function aplusb, you job is to calculate the sum and return it. Challenge -Can you do it with out + operation? +Of course you can just return a + b to get accepted. But Can you challenge not do it like that? Clarification Are a and b both 32-bit integers? - - Yes. +Yes. +Can I use bit operation? + +Sure you can. +Tags Expand +Cracking The Coding Interview Bit Manipulation + -Thinking process: -Bit operation. Just to remmeber this problem, doing A+B using bit. */ +/* +Thought: + Bit operation. Just to remmeber this problem, doing A+B using bit. +*/ class Solution { - /* - * param a: The first integer - * param b: The second integer - * return: The sum of a and b - */ public int aplusb(int a, int b) { while (b != 0) { int carry = a & b; @@ -35,3 +53,5 @@ public int aplusb(int a, int b) { } }; + +``` \ No newline at end of file diff --git a/Java/Add Binary.java b/Java/Add Binary.java index e8d1f35..3bbd79f 100644 --- a/Java/Add Binary.java +++ b/Java/Add Binary.java @@ -1,4 +1,14 @@ +E + +方法一:土办法没技术,把binary换成数字,加起来,再换成binary。如果input很大,那么很可能int,long都hold不住。不保险。 + +方法二:一般方法,string化为charArray,然后逐位加起,最后记得处理多余的一个carry on + + +``` /* +Add Binary + Given two binary strings, return their sum (also a binary string). Example @@ -9,10 +19,13 @@ Given two binary strings, return their sum (also a binary string). Return 100 Tags Expand -String Binary +String Binary Facebook + +*/ +/* //Thougths: 1. Turn string binary format into integer 2. add integer @@ -20,7 +33,6 @@ Given two binary strings, return their sum (also a binary string). Note: this just test if we know how to manipulate string/binary/Integer */ - public class Solution { /** * @param a a number @@ -39,3 +51,40 @@ public String addBinary(String a, String b) { return Integer.toBinaryString(sum); } } + + + +/* + Thought: + Use binary property, add all and move carry-on + String to charArray +*/ + +public class Solution { + public String addBinary(String a, String b) { + if (a == null || b == null || a.length() == 0 || b.length() == 0) { + return null; + } + char[] shortArr = a.length() < b.length() ? a.toCharArray() : b.toCharArray(); + char[] longArr = a.length() < b.length() ? b.toCharArray() : a.toCharArray(); + int carry = 0; + int shortVal = 0; + int nextCarry = 0; + int diff = longArr.length - shortArr.length; + for (int i = longArr.length - 1; i >= 0; i--) { + shortVal = (i - diff) >= 0 ? shortArr[i - diff] - '0': 0; + nextCarry = (longArr[i] - '0' + shortVal + carry) / 2; + longArr[i] =(char)((longArr[i] - '0' + shortVal + carry) % 2 + '0'); + carry = nextCarry; + } + + if (carry != 0) { + return "1" + new String(longArr); + } + + return new String(longArr); + } +} + + +``` \ No newline at end of file diff --git a/Java/Add Two Numbers II.java b/Java/Add Two Numbers II.java index 55d3fba..5b3a138 100644 --- a/Java/Add Two Numbers II.java +++ b/Java/Add Two Numbers II.java @@ -1,9 +1,13 @@ -方向相反。巧用stack. +M + +LinkedList并没有反过来,那么自己反: + 方向相反。巧用stack. + +做加法都一样: + 1. carrier + 2. carrier = (rst + carrier) / 10 + 3. rst = (rst + carrier) % 10 -做加法都一样: -1. carrier -2. carrier = (rst + carrier) / 10 -3. rst = (rst + carrier) % 10 ``` /* You have two numbers represented by a linked list, where each node contains a single digit. diff --git a/Java/Add Two Numbers.java b/Java/Add Two Numbers.java new file mode 100644 index 0000000..116250e --- /dev/null +++ b/Java/Add Two Numbers.java @@ -0,0 +1,73 @@ +E + +LinkedList都已经反转好了,直接做。 + +遍历两个l1,l2把carry-on处理好,每次生成一个新node,最后检查carry-on。 + +跟Add Binary的理解方式一模一样。 + + +``` +/* +You have two numbers represented by a linked list, +where each node contains a single digit. +The digits are stored in reverse order, +such that the 1's digit is at the head of the list. +Write a function that adds the two numbers and returns the sum as a linked list. + +Example +Given 7->1->6 + 5->9->2. That is, 617 + 295. + +Return 2->1->9. That is 912. + +Given 3->1->5 and 5->9->2, return 8->0->8. + +Tags Expand +Cracking The Coding Interview Linked List High Precision +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param l1: the first list + * @param l2: the second list + * @return: the sum list of l1 and l2 + */ + public ListNode addLists(ListNode l1, ListNode l2) { + ListNode rst = new ListNode(0); + ListNode dummy = rst; + int carrier = 0; + //while + while (l1 != null || l2 != null) { + if (l1 != null) { + carrier += l1.val; + l1 = l1.next; + } + if (l2 != null) { + carrier += l2.val; + l2 = l2.next; + } + rst.next = new ListNode(carrier % 10); + carrier = carrier / 10; + rst = rst.next; + } + //check the carrier + if (carrier == 1) { + rst.next = new ListNode(1); + } + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Java/Add and Search Word.java b/Java/Add and Search Word.java old mode 100644 new mode 100755 index 8d8f0bf..b55a693 --- a/Java/Add and Search Word.java +++ b/Java/Add and Search Word.java @@ -1,39 +1,38 @@ -Trie结构, prefix tree. -节点里面有char, isEnd, HashMap -记得怎么造trie:无增有移,没node就加,有Node就移动。 -寻找word也一样,无错有移。 +M + +Trie结构, prefix tree的变形: '.'可以代替任何字符,那么就要iterate这个node所有的children. + +节点里面有char, isEnd, HashMap +Build trie = Insert word:没node就加,有node就移动。 +Search word:没有node就报错. 到结尾return true + +这题因为'.'可以代替任何possible的字符,没一种都是一个新的path,所以recursive做比较好些。 +(iterative就要queue了,麻烦点) + ``` /* -Design a data structure that supports the following two operations: +Design a data structure that supports the following two operations: addWord(word) and search(word) -void addWord(word) +search(word) can search a literal word or a regular expression string containing only letters a-z or .. -bool search(word) - -search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter. Example addWord("bad") - addWord("dad") - addWord("mad") - -search("pad") -> false - -search("bad") -> true - -search(".ad") -> true - -search("b..") -> true - +search("pad") // return false +search("bad") // return true +search(".ad") // return true +search("b..") // return true Note You may assume that all words are consist of lowercase letters a-z. -Tags: -Backtracking +Tags Expand +Trie */ + + /* Build the WordDictionary like a TrieTree. Note: the '.' indicates any letter, which means we'd have to traverse through all possible letters in current level. @@ -43,8 +42,6 @@ bool search(word) TrieNode contains that char, boolean, and HashMap of children */ -//NOT DONE YET: http://www.lintcode.com/en/problem/add-and-search-word/# - public class WordDictionary { class TrieNode{ HashMap children; @@ -108,17 +105,4 @@ public boolean searchHelper(TrieNode root, String word, int index) { // wordDictionary.search("pattern"); - - - - - - - - - - - - - ``` \ No newline at end of file diff --git a/Java/Alien Dictionary.java b/Java/Alien Dictionary.java new file mode 100755 index 0000000..9feb681 --- /dev/null +++ b/Java/Alien Dictionary.java @@ -0,0 +1,64 @@ +H + +Not Done yet。 Topological sort. + +``` + +/* +There is a new alien language which uses the latin alphabet. +However, the order among letters are unknown to you. +You receive a list of words from the dictionary, where words are sorted lexicographically by the rules of this new language. +Derive the order of letters in this language. + +For example, +Given the following words in dictionary, + +[ + "wrt", + "wrf", + "er", + "ett", + "rftt" +] +The correct order is: "wertf". + +Note: +You may assume all letters are in lowercase. +If the order is invalid, return an empty string. +There may be multiple valid order of letters, return any one of them is fine. +Hide Company Tags Google Facebook +Hide Tags Graph Topological Sort +Hide Similar Problems (M) Course Schedule II + +*/ + +/* + NOT DONE + Thoughts: + They have sink node. They form a valid tree, without sycle. + A char can visit another node, does not mean they have order. + A char appear in a lower row means they have different order. + For 1st column, w appears before e, e appears before r. + For 2nd column:r appears before t, t appears before f + For 3rd col: t appears before f. + For 4th col, nothing to compare. + So make in[][]: [w,e] [e,r][r,t][t,f] based on the possible order. + + Then do topological sort on the sequence and mark the sequence like in course schedule II +*/ + +public class Solution { + public String alienOrder(String[] words) { + + } +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Java/Anagrams.java b/Java/Anagrams.java old mode 100644 new mode 100755 index 2d1395c..bd0729e --- a/Java/Anagrams.java +++ b/Java/Anagrams.java @@ -1,22 +1,29 @@ -hashtable 的做法。 -toCharArray -Arrays.sort -Stirng.valueOf(char[]) +M +1. HashMap 的做法. sort每个string, 存进HashMap, 重复的就是anagrams,最后输出。 + toCharArray + Arrays.sort + Stirng.valueOf(char[]) + 时间n*L*O(logL),L是最长string的长度。 -http://www.jiuzhang.com/solutions/anagrams/ -做法不太一样 lOl -1. take each string, count the occurrance of the 26 letters. save in int[]count. -2. hash the int[] count and output a unique hash value. - hash = hash * a + num - a = a * b. -3. save to hashmap in the same way as we do. +2. Arrays.toString(arr)的做法。arr是int[26], assuming only have 26 lowercase letters. +Count occurrance, 然后convert to String,作为map的key. +Time complexity: nO(L) + +3. 另一种做法:http://www.jiuzhang.com/solutions/anagrams/ + 1. take each string, count the occurrance of the 26 letters. save in int[]count. + 2. hash the int[] count and output a unique hash value. + hash = hash * a + num + a = a * b. + 3. save to hashmap in the same way as we do. + +这一步把for s: strs 里面的时间复杂度降到了O(L). L = s.length(). +Need to work on the getHash() function. + +时间变成n*O(L). Better. -这一步把for s: strs -里面的时间复杂度降到了O(L). L = s.length() -而普通的,for 里面的时间复杂度是 Llog(L) ``` /* Given an array of strings, return all groups of strings that are anagrams. @@ -35,6 +42,44 @@ */ +/* +//2.29.2016 + use int[26] assuming it's all lowercase letters + count each string char in a letter array int[], convert the array into string. + HashMap carray string as key, and actualy string as value + outupt all values +*/ +public class Solution { + public List anagrams(String[] strs) { + List rst = new ArrayList(); + if (strs == null || strs.length == 0) { + return rst; + } + HashMap> map = new HashMap>(); + + for (int i = 0; i < strs.length; i++) { + int[] arr = new int[26]; + for (int j = 0; j < strs[i].length(); j++) { + arr[strs[i].charAt(j) - 'a'] += 1; + } + String arrString = Arrays.toString(arr); + if (!map.containsKey(arrString)) { + map.put(arrString, new ArrayList()); + } + map.get(arrString).add(strs[i]); + } + + //Output + for (Map.Entry> entry : map.entrySet()) { + if (entry.getValue().size() >= 2) + rst.addAll(entry.getValue()); + } + + return rst; + } +} + + /* Recap 12.09.2015 diff --git a/Java/Backpack II.java b/Java/Backpack II.java index c780c23..74f50ea 100644 --- a/Java/Backpack II.java +++ b/Java/Backpack II.java @@ -1,16 +1,24 @@ -做了backpack I, 这个就如出一辙。 -想法还是,选了A[i-1] 或者没选A[i]. -一路往前跑不回头。就出来了。 +M + +做了Backpack I, 这个就如出一辙。 +想法还是,选了A[i-1] 或者没选A[i]. +一路往前跑不回头。就出来了。 +其实这个Backpack II 还更容易看懂代码。 + +O(m)的做法: +想想,的确我们只care 最后一行,所以一个存value的就够了。 +注意:和bakcpackI的 O(m)一样的,j是倒序的。如果没有更好的j,就不要更新。就是这个道理。 -O(m)的做法。想想,的确我们只care 最后一行,所以一个存value的就够了。 注意:和bakcpackI的 O(m)一样的,j是倒序的。如果没有更好的j,就不要更新。就是这个道理。 ``` /* -Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack? +Given n items with size Ai and value Vi, and a backpack with size m. +What's the maximum value can you put into the backpack? Example -Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9. +Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. +The maximum value is 9. Note You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m. @@ -79,11 +87,12 @@ public int backPackII(int m, int[] A, int V[]) { /* To use just O(m) sapce. - Just like in Backpack I, at the end, we only care about the last row. Why not just maintain a row, always keep the max value. + Just like in Backpack I, at the end, we only care about the last row. + Why not just maintain a row, always keep the max value. Note: Only update dp[j] if adding A[i-1] would be greater than current dp[j] - It's a bit hard to come up with this... but it's good exercise to build brain a bit. + It's a bit hard to come up with this... but it's good exercise. */ public class Solution { @@ -110,6 +119,4 @@ public int backPackII(int m, int[] A, int V[]) { - - ``` \ No newline at end of file diff --git a/Java/Backpack.java b/Java/Backpack.java index 713728e..d2a8d92 100644 --- a/Java/Backpack.java +++ b/Java/Backpack.java @@ -1,29 +1,38 @@ -记得这个DP。 -row是item大小: 0, A[0], A[1] ... A[A.length -1] -col是背包累积的size: 0, 1, 2, ... m. +M + +DP。 + row是item大小: 0, A[0], A[1] ... A[A.length -1] + col是背包累积的size: 0, 1, 2, ... m. + +想法: + dp[i][j]有这么i-1个item, 用他们可否组成size为j的背包?true/false. (反过来考虑了,不是想是否超过size j, 而是考虑是否能拼出exact size == j)。 + 注意注意:虽然dp里面一直存在i的位置,实际上考虑的是在i位置的时候,看前i-1个item. -想法是这样: -dp[i][j]有这么i-1个item, 用他们可否组成size为j的背包?true/false. (反过来考虑了,不是想是否超过size j, 而是考虑是否能拼出exact size == j)。 -注意注意:虽然dp里面一直存在i的位置,实际上考虑的是在i位置的时候,看前i-1个item. 看一遍code,会发现: - 1. picked A[i-1] 如果上一个item, A[i-1]被加了上来, 用j-A[i-1]看看,是否这再前一步也true. true就好啦! - 2. did not pick A[i-1]. 那就是说,不加上A[i-1], 上一行d[i-1][j]还是需要是true。 + 1. picked A[i-1]: 如果上一个item, A[i-1],被加了上来, 用j-A[i-1]看看,是否这再前一步也true. true就好啦。 + 2. did not pick A[i-1]: 那就是说,不加上A[i-1], 上一行d[i-1][j]还是需要是true。 + +最后: + 跑一边dp 最下面一个row. 从末尾开始找,最末尾的一个j (能让dp[i][j] == true)的,就是最多能装的大小 :) + +时间,空间都是:O(mn) -最后: -跑一边dp 最下面一个row. 从末尾开始找,最末尾的一个j (能让dp[i][j] == true)的,就是最多能装的大小 :) +再有: +O(m)时间的做法,具体看solution. 注意j是倒序的啊! +依然是O(mn)的空间 -再有: -O(m)的做法,注意j是倒序的啊! ``` /* Given n items with size Ai, an integer m denotes the size of a backpack. How full you can fill this backpack? Example -If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select [2, 3, 5], so that the max size we can fill this backpack is 10. If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack. +If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select [2, 3, 5], +so that the max size we can fill this backpack is 10. +If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack. You function should return the max size we can fill in the given backpack. @@ -45,8 +54,8 @@ Thoughts: Recap on 12.02.2015 State DP[i][j]: i is the index of Ai, and j is the size from (0 ~ m). - It means: depending if we added A[i-1], can we add up to j-space?Return ture/false. - Note: that is, even j == 0, and I have a item with size == 2, I can still choose not to add, which means the backpack can reach j ==0. True. + It means: depending if we added A[i-1], can we full-fill j-space? Return ture/false. + Note: that is, even j == 0, and I have a item with size == 0. There is nothing to add, which means the backpack can reach j == 0. True. However, if we have a item with size == 2, but I need to fill space == 1. I will either pick/not pick item of size 2; either way, can't fill a backpack with size 1. False; Function: @@ -68,16 +77,16 @@ public int backPack(int m, int[] A) { for (int i = 1; i <= A.length; i++) { for (int j = 0; j <= m; j++) { - //added A[i - 1] + //j is large enough: if (j - A[i - 1] >= 0) { + //not added A[i - 1] or added A[i - 1] dp[i][j] = dp[i - 1][j] || dp[i - 1][j - A[i - 1]]; - } else { - //not added A[i - 1]; + } else {// j not large enough, ofcourse not adding A[i-1] dp[i][j] = dp[i - 1][j]; } } } - + //Largest possible size with dp[j] == true for (int j = m; j >= 0; j--) { if (dp[A.length][j]) { return j; @@ -89,53 +98,6 @@ public int backPack(int m, int[] A) { -/* -Thoughts: -Well, I kind of forgot about how we did this in algorithm class, but here we go, after a bit research: -DP[i][j] means: if i number of items in A, can we fill the bag size of j? Then, save a boolean in DP[i][j]. That means, if i items are too much for j? - -So, there are two cases: -1. A[i] is unfortunately too big to fit into size j, so skip item A[i] and use DP[i-1][j]. -2. OR, the other case: A[i] fits in well. We realize 2 things: - a. first (i-1)th items much fit in well into the bag size of (j - A[i - 1]): DP[i-1][j - A[i-1]]. Basically says items must be fit in (true) before adding A[i] - b. AND (j - A[i - 1]) must >= 0 to have space for next item i. - -End: -Iterate through j:(m ~ 0), and return j, if DP[A.length][j] is true. We are starting from m, because we need the largest number j. - -This is 2D array version: memory mxn, space mxn - -*/ - -public class Solution { - /** - * @param m: An integer m denotes the size of a backpack - * @param A: Given n items with size A[i] - * @return: The maximum size - */ - public int backPack(int m, int[] A) { - if (A == null || m == 0) { - return 0; - } - - boolean[][] DP = new boolean[A.length + 1][m + 1]; - DP[0][0] = true; - for (int i = 1; i <= A.length; i++) { - for (int j = 0; j <= m; j++) { - DP[i][j] = DP[i - 1][j] || (j - A[i - 1] >= 0 && DP[i - 1][j - A[i - 1]]); - } - } - - for (int j = m; j >= 0; j--) { - if (DP[A.length][j]) { - return j; - } - } - return 0; - } -} - - /* 1D array: memory mxn, space m. Tricky tho ... diff --git a/Java/Balanced Binary Tree.java b/Java/Balanced Binary Tree.java old mode 100644 new mode 100755 index 076d297..8c0f24a --- a/Java/Balanced Binary Tree.java +++ b/Java/Balanced Binary Tree.java @@ -1,17 +1,18 @@ +M + 1. DFS using depth marker: 每个depth都存一下。然后如果有不符合条件的,存为-1. - 一旦有-1, 就全部返回。 - 最后比较返回结果是不是-1. 是-1,那就false + 一旦有-1, 就全部返回。 + 最后比较返回结果是不是-1. 是-1,那就false. + Traverse 整个tree, O(n) -2. 从基本的题目理解考虑,想到leaf node的情况。如果判断了leaf node, 那其他node应该就是可以recursive。 - 直接在isBalanced上面recursive. - 然后这个可能是个小小的优化,因为不需要计算所有的depth.一旦发现一个false,其他的就不需要计算,直接返回了。 +2. Only calculate depth using maxDepth function. Same concept as in 1, but cost more traversal efforts. ``` /* -46% Accepted Given a binary tree, determine if it is height-balanced. -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. +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. Example Given binary tree A={3,9,20,#,#,15,7}, B={3,#,20,15,7} @@ -24,7 +25,7 @@ The binary tree A is a height-balanced binary tree, but B is not. Tags Expand -Tree Depth First Search +Binary Search Divide and Conquer Recursion */ @@ -41,49 +42,6 @@ */ -/* - 12.11.2015 - Recap: - The original way of marking depth and -1 is good. However, that has to traverse entire tree. - - Today, let's think about the leaf case, and see if we can directly recurse on isBalanced itself. - leaf case: - root == null, return true; - left = root.left; right = root.right; - left == null && right == null : true; - - left == null && right != null && (right.left != null || right.right != null) { - false; - } - - need to isBalance(left) && isBalance(right). -*/ - -public class Solution { - /** - * @param root: The root of binary tree. - * @return: True if this Binary tree is Balanced, or false. - */ - public boolean isBalanced(TreeNode root) { - if (root == null || (root.left == null && root.right == null)) { - return true; - } - - TreeNode left = root.left; - TreeNode right = root.right; - //One of left or right is null. - if (left == null && (right.left != null || right.right != null)) { - return false; - } - if (right == null && (left.left != null || left.right != null)) { - return false; - } - //none of left or right is null - return isBalanced(left) && isBalanced(right); - } -} - - /* Thinking process: @@ -94,31 +52,90 @@ same process as maxDepth() method. at the top return, check if -1. */ -public class Solution { - /** - * @param root: The root of binary tree. - * @return: True if this Binary tree is Balanced, or false. - */ +/* 3.3.2016 recap: + Recursive 1: + Use helper to calculate depth, and also check if left/right depth differ by 1. If all good, return actual depth +*/ + + public class Solution { public boolean isBalanced(TreeNode root) { - return maxDepth(root) != -1; + if (root == null) { + return true; + } + return helper(root) > 0; } - public int maxDepth(TreeNode root) { - if (root == null) { + public int helper(TreeNode node) { + if (node == null) { return 0; } + int leftDepth = helper(node.left); + int rightDepth = helper(node.right); - int left = maxDepth(root.left); - int right = maxDepth(root.right); + if (leftDepth < 0 || rightDepth < 0 || Math.abs(leftDepth - rightDepth) > 1) { + return Integer.MIN_VALUE; + } - if (Math.abs(left - right) > 1 || left == -1 || right == -1) { - return -1; + return Math.max(leftDepth, rightDepth) + 1; + } +} + + +/* + Recursive 2: + Calculate a node's maxDepth. Compare a parent node's sub tree for maxDepth +*/ +public class Solution { + public boolean isBalanced(TreeNode root) { + if (root == null) { + return true; } + int leftDepth = maxDepth(root.left); + int rightDepth = maxDepth(root.right); - return Math.max(left, right) + 1; + if (Math.abs(leftDepth - rightDepth) > 1) { + return false; + } + return isBalanced(root.left) && isBalanced(root.right); + } + + public int maxDepth(TreeNode node) { + if (node == null) { + return 0; + } + return Math.max(maxDepth(node.left), maxDepth(node.right)) + 1; } } + +/* + Failed Solution: + check cases: + root == null, return true; + left = root.left; right = root.right; + left == null && right == null : true; + left == null && right != null && (right.left != null || right.right != null) { + false; + } + return isBalance(left) && isBalance(right). + + failed case:[1,2,2,3,3,null,null,4,4] + 1 + 2 2 + 3 3 + 4 4 +Previous notes: +2. 从基本的题目理解考虑,想到leaf node的情况。如果判断了leaf node, 那其他node应该就是可以recursive。 + 直接在isBalanced上面recursive. + 关键return false的判断情况:如果有个node是null, 那么同一行相邻的那个,一旦有了children,那么就说明两个分支的depth已经是>=2了,那么就return false. + + 然后这个可能是个小小的优化,因为不需要计算所有的depth.一旦发现一个false,其他的就不需要计算,直接返回了。 + + + +*/ + + ``` \ No newline at end of file diff --git a/Java/Best Time to Buy and Sell Stock I.java b/Java/Best Time to Buy and Sell Stock I.java index a71506f..f33f2dd 100644 --- a/Java/Best Time to Buy and Sell Stock I.java +++ b/Java/Best Time to Buy and Sell Stock I.java @@ -1,24 +1,37 @@ -n天就买卖一次。 -每天都算算目前最小值Min是多少。O(n) -每天都算算和当下的Min买卖,profit最大多少。 +M + +理解意思是关键: + 每天都就交易价格,n天只让买卖一次,那就找个最低价买进,找个最高价卖出。 + 记录每天最小值Min是多少。O(n) + 每天都算和当下的Min买卖,profit最大多少。 + + ``` /* Say you have an array for which the ith element is the price of a given stock on day i. -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. +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. +Have you met this question in a real interview? Yes Example +Given an example [3,2,3,1,2], return 1 + Tags Expand -Array Dynamic Programming +Greedy Enumeration Array Facebook Uber + +*/ + +/* -Thinking process: +Thoughts First to understand what this question is asking: Each element is a price of the same stock on that specific day. Of course we want to buy in with min-price and sell out with max-price. Find the min-price by looping through the array. Find the max-profit: price[i] - min-price, which requires a loop through the loop again. We put above 2 tasks into one-pass for loop -*/ +*/ public class Solution { /** * @param prices: Given an integer array diff --git a/Java/Best Time to Buy and Sell Stock II.java b/Java/Best Time to Buy and Sell Stock II.java index 90196d9..2ca5b6c 100644 --- a/Java/Best Time to Buy and Sell Stock II.java +++ b/Java/Best Time to Buy and Sell Stock II.java @@ -1,16 +1,34 @@ -找涨幅最大的区间,买卖。 -飞似得涨,到峰顶,就卖。 +M + +和Stock I 的区别:可以买卖多次,求总和的最大盈利。 + +找涨幅最大的区间,买卖: +找到低谷,买进:peek = start + 1 时候,就是每次往前走一步;若没有上涨趋势,继续往低谷前进。 +涨到峰顶,卖出:一旦有上涨趋势,进一个while loop,涨到底, 再加个profit. + +中间的: + profit += prices[peek - 1] - prices[start]; 听特别的。 + 当没有上涨趋势时候,peek-1也就是start, 所以这里刚好profit += 0. + +O(n) + ``` /* Say you have an array for which the ith element is the price of a given stock on day i. -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). +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). Example +Given an example [2,1,2,0,1], return 2 + Tags Expand -Greedy Array +Greedy Enumeration Array +*/ -Thinking process: +/* +Thought: In this case, since we know the entire stock price for all days in the array, we want to this: Sell it at nearest peek price and buy it on the next dropped price, then sell again at next peek. Two pointers, start and peek, to track the starting point and the peek. @@ -19,9 +37,10 @@ Design an algorithm to find the maximum profit. You may complete as many transac Inner while loop that finds the peek from start. Note: peek always has index >= start+1. Sum up all profit and return it. -Tricky thing: we are looking for max profit, but does not require to sell the stock by end of array. So if the price is dropping, we are not selling and we are not losing/winning anything. -*/ +Tricky thing: we are looking for max profit, but does not require to sell the stock by end of array. +So if the price is dropping, we are not selling and we are not losing/winning anything. +*/ class Solution { /** * @param prices: Given an integer array diff --git a/Java/Best Time to Buy and Sell Stock III .java b/Java/Best Time to Buy and Sell Stock III .java index 90a42f1..699e1d2 100644 --- a/Java/Best Time to Buy and Sell Stock III .java +++ b/Java/Best Time to Buy and Sell Stock III .java @@ -1,29 +1,42 @@ -两次卖出机会。那反正就是:找峰头;然后往下再找一个峰头。 -怎么样在才能Optimize呢。 -从两边同时开始找Max. -leftProfit是从左往右,每个i点上的最大Profit。 -rightProfit是从i点开始到结尾,每个点上的最大profit. -那么把左右两边在i上,两边相加的最大值找到就可以了。 +M + +比stock II 多了一个限制:只有2次卖出机会。也就是:找峰头;然后往下再找一个峰头。 + +怎么样在才能Optimize两次巅峰呢? + +从两边同时开始找Max!(棒棒的想法) + + leftProfit是从左往右,每个i点上的最大Profit。 + rightProfit是从i点开始到结尾,每个点上的最大profit. + 那么在i点上,就是leftProfit,和右边rightProfit的分割点。在i点,leftProfit+rightProfit相加,找最大值。 + +三个O(n),还是O(n) + ``` /* Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. +Example +Given an example [4,4,6,1,1,4,2,5], return 6. + Note You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). -Example Tags Expand -Array Dynamic Programming +Enumeration Forward-Backward Traversal Array + +*/ -Thinking process: +/* +Thoughts: Idea from NineChapter: use two arrays to mark max values, however the max values are calculated from left/right sides. Left[] marks max profit value in the range from a left-index to current index. Tracking left-min. Right[] marks max profit value in the range from current index to a right-index. Tracking right-max. If looking at right[i] and left[i] together at index i, they are always representing left-max-profit value and right-max-profit value. Add them together and get results. -*/ +*/ class Solution { /** * @param prices: Given an integer array @@ -57,11 +70,4 @@ public int maxProfit(int[] prices) { - - - - - - - ``` \ No newline at end of file diff --git a/Java/Best Time to Buy and Sell Stock IV.java b/Java/Best Time to Buy and Sell Stock IV.java index 56aba94..4979ca2 100644 --- a/Java/Best Time to Buy and Sell Stock IV.java +++ b/Java/Best Time to Buy and Sell Stock IV.java @@ -1,6 +1,28 @@ -有问题。还不是非常理解: -best time to buy and sell stock: 为什么 i-1天的卖了又买,可以和第 i 天的卖合成一次交易? -因为每天交易的price是定的。所以卖了又买,等于没卖!这就是可以合并的原因。要对价格敏感啊少年。 +H + +记得要理解: 为什么 i-1天的卖了又买,可以和第 i 天的卖合成一次交易? + 因为每天交易的price是定的。所以卖了又买,等于没卖!这就是可以合并的原因。要对价格敏感啊少年。 + +Inspired from here: +http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html + +局部最优解 vs. 全局最优解: + local[i][j] = max(global[i – 1][j – 1] + diff, local[i – 1][j] + diff) + global[i][j] = max(global[i – 1][j], local[i][j]) + +local[i][j]: 第i天,当天一定进行第j次交易的profit +global[i][j]: 第i天,总共进行了j次交易的profit. + +local[i][j]和global[i][j]的区别是:local[i][j]意味着在第i天一定有交易(卖出)发生。 + 当第i天的价格高于第i-1天(即diff > 0)时,那么可以把这次交易(第i-1天买入第i天卖出)跟第i-1天的交易(卖出)合并为一次交易,即local[i][j]=local[i-1][j]+diff; + 当第i天的价格不高于第i-1天(即diff<=0)时,那么local[i][j]=global[i-1][j-1]+diff,而由于diff<=0,所以可写成local[i][j]=global[i-1][j-1]。 + (Note:在我下面这个solution里面没有省去 +diff) + +global[i][j]就是我们所求的前i天最多进行k次交易的最大收益,可分为两种情况: + 如果第i天没有交易(卖出),那么global[i][j]=global[i-1][j]; + 如果第i天有交易(卖出),那么global[i][j]=local[i][j]。 + + ``` /* @@ -29,11 +51,6 @@ */ class Solution { - /** - * @param k: An integer - * @param prices: Given an integer array - * @return: Maximum profit - */ public int maxProfit(int k, int[] prices) { if (prices == null || prices.length < 2 || k <= 0) { return 0; diff --git a/Java/Binary Representation.java b/Java/Binary Representation.java index 3db457d..188d5e6 100644 --- a/Java/Binary Representation.java +++ b/Java/Binary Representation.java @@ -1,19 +1,23 @@ -主要就是要分两半。 +H -Integer那一半好弄,Loop里面 num%2, num/2就好。 -Decimal那边复杂点,bit == 1的数学条件是: -当下num * 2 - 1 >= 0... -然后循环时候还要 num * 2 - 1, 或者 num * 2 +首先要分两半解决,断点是'.': str.split("\\."); -因为num是 double, 小于0的小数,所以其实这样做下去很可能无限循环。 +Integer那一半好弄,whie loop里: num%2, num/2。 -所以题目也才有了32BIT的要求! +Decimal那边复杂点. + bit == 1的数学条件:当下num * 2 >= 1。 更新: num = num * 2 - 1; + bit == 0的数学条件: num * 2 < 1. 更新: num = num * 2 + +注意:num是 double, 小数在 (num = num * 2 -1)的公式下可能无限循环. 因此check: num重复性,以及binary code < 32 bit. + +(所以题目也才有了32BIT的要求!) ``` /* -Given a (decimal - e.g. 3.72) number that is passed in as a string, return the binary representation that is passed in as a string. If the fractional part of the number can not be represented accurately in binary with at most 32 characters, return ERROR. +Given a (decimal - e.g. 3.72) number that is passed in as a string, +return the binary representation that is passed in as a string. +If the fractional part of the number can not be represented accurately in binary with at most 32 characters, return ERROR. -Have you met this question in a real interview? Yes Example For n = "3.72", return "ERROR". @@ -44,10 +48,6 @@ Given a (decimal - e.g. 3.72) number that is passed in as a string, return the b */ public class Solution { - /** - *@param n: Given a decimal number that is passed in as a string - *@return: A string - */ public String binaryRepresentation(String n) { if (n.length() == 0 || n.equals("0")) { return "0"; diff --git a/Java/Binary Search Tree Iterator.java b/Java/Binary Search Tree Iterator.java old mode 100644 new mode 100755 index 0333f5a..c76ad88 --- a/Java/Binary Search Tree Iterator.java +++ b/Java/Binary Search Tree Iterator.java @@ -1,17 +1,41 @@ -理解binary search tree inorder traversal的规律。 -都是先找left.left.left ....left. 为top。 -然后再找parent,然后再right. +H + +用O(h)空间的做法: + +理解binary search tree inorder traversal的规律: + 先找left.left.left ....left 到底,这里是加进stack. + 然后考虑parent,然后再right. + +例如这题: + stack里面top,也就是tree最左下角的node先考虑,取名rst. + 其实这个rst拿出来以后, 它也同时是最底层left null的parent,算考虑过了最底层的parent。 + 最后就考虑最底层的parent.right, 也就是rst.right. + +注意: + next()其实有个while loop, 很可能是O(h).题目要求average O(1),所以也是okay的. + + +用O(1)空间的做法:不存stack, 时刻update current为最小值。 + +找下一个最小值,如果current有right child: + 和用stack时的iteration类似,那么再找一遍current.right的left-most child,就是最小值了。 + +如果current没有right child: + 那么就要找current node的右上parent, search in BinarySearchTree from root. + +注意: + 一定要确保找到的parent满足parent.left == current. + 反而言之,如果current是parent的 right child, 那么下一轮就会重新process parent。 + 但是有错:binary search tree里面parent是小于right child的,也就是在之前一步肯定visit过,如此便会死循环。 + -这个题目里面找到rst之后,首先考虑这个rst.right - 其实rst在这里虽然是most left node, 但对于rst.right来说,其实它也是parent. -所以每次把left全部弄一边的时候,parent node其实也都是顾及到了的。 ``` /* Design an iterator over a binary search tree with the following rules: Elements are visited in ascending order (i.e. an in-order traversal) next() and hasNext() queries run in O(1) time in average. -Have you met this question in a real interview? Yes + Example For the following binary search tree, in-order traversal by using iterator is [1, 6, 10, 11, 12] @@ -29,14 +53,7 @@ Extra memory usage O(h), h is the height of the tree. Binary Tree LintCode Copyright Non Recursion Binary Search Tree Google LinkedIn Facebook */ -/* - Thoughts://http://blog.csdn.net/u014748614/article/details/46800891 - Put all left nodes into stack. Then top of stack must be the first element in in-order-traversal. - We never add right node into stack directly, but ever time before returnning the rst node, we take care of rst.right right away. - That is, find next() when rst.right as root. - very smart use of a 'currnt' node. - It's like a pointer on the tree, but only operates when that current node is not null, and under condition of having left child. -*/ + /** * Definition of TreeNode: @@ -55,6 +72,58 @@ That is, find next() when rst.right as root. * do something for node * } */ + +//Recap 02.24.2016: Similar to solution below. O(h) space. +//Stack, inorder traversal; first add left node till end. Each next() trigger a iteration. +public class BSTIterator { + public Stack stack = new Stack(); + + //@param root: The root of binary tree. + //Add till end of left + public BSTIterator(TreeNode root) { + if (root == null) { + return; + } + stack.push(root); + while (root.left != null) { + stack.push(root.left); + root = root.left; + } + } + + //@return: True if there has next node, or false + public boolean hasNext() { + return stack.size() > 0; + } + + //@return: return next node + public TreeNode next() { + TreeNode node = stack.pop(); + if (node.right != null) { + TreeNode temp = node.right; + stack.push(temp); + while (temp.left != null) { + stack.push(temp.left); + temp = temp.left; + } + } + return node; + } +} + + + +/* + Previous correct implementation, O(h) space. + Thoughts:http://blog.csdn.net/u014748614/article/details/46800891 + Put all left nodes into stack. Then top of stack must be the first element in in-order-traversal. + We never add right node into stack directly, but ever time before returnning the rst node, we take care of rst.right right away. + That is, find next() when rst.right as root. + very smart use of a 'currnt' node. + It's like a pointer on the tree, but only operates when that current node is not null, and under condition of having left child. + +*/ + public class BSTIterator { public Stack stack = new Stack(); public TreeNode current; @@ -80,13 +149,95 @@ public TreeNode next() { } } +/* + Use O(1) space, which means we will not use O(h) stack. + + To begin: + 1. hasNext()? current.val <= endNode.val to check if the tree is fully traversed. + + 2. Find min via left-most: We can alwasy look for left-most to find next minimum value. + + 3. Once left-most min is checked (name it `current`). Next min will be 2 cases: + If current.right != null, we can keep looking for current.right's left-most child, as next min. + Or, we need to look backwards for parent. Use binary search tree to find current's parent node. + + Note: when doing binary search for parent, make sure it satisfies parent.left = current. + + Because:If parent.right == current, that parent must has been visited before. In binary search tree, + we know that parent.val < parent.right.val. We need to skip this special case, since it leads + to ifinite loop. + +*/ + + +public class BSTIterator { + public TreeNode root; + public TreeNode current; + public TreeNode endNode; + //@param root: The root of binary tree. + public BSTIterator(TreeNode root) { + if (root == null) { + return; + } + this.root = root; + this.current = root; + this.endNode = root; + + while (endNode != null && endNode.right != null) { + endNode = endNode.right; + } + while (current != null && current.left != null) { + current = current.left; + } + } + //@return: True if there has next node, or false + public boolean hasNext() { + return current != null && current.val <= endNode.val; + } + + //@return: return next node + public TreeNode next() { + TreeNode rst = current; + //current node has right child + if (current.right != null) { + current = current.right; + while (current.left != null) { + current = current.left; + } + } else {//Current node does not have right child. + current = findParent(); + } + return rst; + } + + //Find current's parent, where parent.left == current. + public TreeNode findParent(){ + TreeNode node = root; + TreeNode parent = null; + int val = current.val; + if (val == endNode.val) { + return null; + } + while (node != null) { + if (val < node.val) { + parent = node; + node = node.left; + } else if (val > node.val) { + node = node.right; + } else {//node.val == current.val + break; + } + } + return parent; + } +} +``` -``` \ No newline at end of file diff --git a/Java/Binary Search.java b/Java/Binary Search.java deleted file mode 100644 index 5931e4a..0000000 --- a/Java/Binary Search.java +++ /dev/null @@ -1,61 +0,0 @@ -/* -Easy Binary Search Show Result My Submissions - -26% Accepted -Binary search is a famous question in algorithm. - -For a given sorted array (ascending order) and a target number, find the first index of this number in O(log n) time complexity. - -If the target number does not exist in the array, return -1. - -Example -If the array is [1, 2, 3, 3, 4, 5, 10], for given target 3, return 2. - -Challenge -If the count of numbers is bigger than MAXINT, can your code work properly? - -Tags Expand -Binary Search - -- -*/ - -class Solution { - /** - * @param nums: The integer array. - * @param target: Target to find. - * @return: The first position of target. Position starts from 0. - */ - public int binarySearch(int[] nums, int target) { - //write your code here - if (nums.length == 0) { - return -1; - } - - int start = 0; - int end = nums.length - 1; - int mid; - - while (start + 1 < end) { - mid = start + (end - start) / 2; - if (nums[mid] < target) { - start = mid; - } else if (nums[mid] > target) { - end = mid; - } else { - end = mid; - } - } - - if (nums[start] == target) { - return start; - } else if (nums[end] == target) { - return end; - } else { - return -1; - } - } - - -} - diff --git a/Java/Binary Tree Inorder Traversal.java b/Java/Binary Tree Inorder Traversal.java old mode 100644 new mode 100755 index c53c3e8..95fd667 --- a/Java/Binary Tree Inorder Traversal.java +++ b/Java/Binary Tree Inorder Traversal.java @@ -1,19 +1,22 @@ -1. Recursive: Divide and Conquer -2. Stack: add left nodes all the way; then print curr; move to right, add right if possible. -3. Recursive with helper method +E +法一: +Recursive: Divide and Conquer, with helper(dfs) method -注意inorder traversal在check right node的事后, -不论right == null or != null, 每次都要强行move to right. +法二: +Stack: +Add left nodes all the way +Print curr +Move to right, add right if possible. + +注意stack.pop()在加完left-most child 的后,一定要curr = curr.right. -如果不node = node.right, -很可能发生窘境: -node alays = stack.top(), 然后stack.top()一直是一开始把left 全部遍历的内容。所以就会infinite loop, 永远在左边上下上下。 +若不右移,很可能发生窘境: +curr下一轮还是去找自己的left-most child,不断重复curr and curr.left, 会infinite loop, 永远在左边上下上下。 ``` /* -Binary Tree Inorder Traversal Given a binary tree, return the inorder traversal of its nodes' values. Example @@ -32,12 +35,76 @@ Can you do it without recursion? Tags Expand -Binary Tree +Recursion Binary Tree Binary Tree Traversal */ /* - 3. Use a helper method, recursively add to rst + recap 3.15.2016 + Recursive +*/ +public class Solution { + public List inorderTraversal(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + dfs(rst, root); + return rst; + } + + public void dfs(List rst, TreeNode node) { + if (node.left != null) { + dfs(rst, node.left); + } + rst.add(node.val); + if (node.right != null) { + dfs(rst, node.right); + } + } +} + + + + +/* + recap 3.15.2016 + Iterative + stack: add left till end; consume top, if has right, add right; push right.left till end of right's left node. +*/ +public class Solution { + public List inorderTraversal(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + Stack stack = new Stack(); + TreeNode node = root; + //Initialize + while (node != null) { + stack.push(node); + node = node.left; + } + //iteratively add && process via inorder traversal + while (!stack.isEmpty()) { + node = stack.pop(); + rst.add(node.val); + if (node.right != null) {//process right, but put right's left children on top of stack + node = node.right; + while (node != null) { + stack.push(node); + node = node.left; + } + } + + } + return rst; + } +} + + +/* + 1. Use a helper method, recursively add to rst */ public class Solution { @@ -78,10 +145,6 @@ public void helper(ArrayList rst, TreeNode node) { */ public class Solution { - /** - * @param root: The root of binary tree. - * @return: Inorder in ArrayList which contains node values. - */ public ArrayList inorderTraversal(TreeNode root) { ArrayList rst = new ArrayList(); if (root == null) { @@ -99,7 +162,7 @@ public ArrayList inorderTraversal(TreeNode root) { //Pop the top node: the curr node curr = stack.pop(); rst.add(curr.val); - //Move to right node, and push to satck if needed + //Move to right node, and push to stack if needed curr = curr.right; if (curr!= null) { stack.push(curr); @@ -110,66 +173,7 @@ public ArrayList inorderTraversal(TreeNode root) { } -/* -Thinking process: -1. Use recursive function: divide and conquer - recursive on left - result.add( current.val) - recursive on right -2. Use Stack to do traversal - while stack not empty { - stack all left childs - result.(current.val) - stack 1 right child - } -*/ -public class Solution { - - //Recursive - Divide and Conquer - public ArrayList inorderTraversal(TreeNode root) { - ArrayList rst = new ArrayList(); - if (root == null) { - return rst; - } - inorderRec(rst, root); - return rst; - } - public void inorderRec(ArrayList rst, TreeNode root) { - if (root == null) { - return; - } - inorderRec(rst, root.left); - rst.add(root.val); - inorderRec(rst, root.right); - } - //Traversal using Stack - public ArrayList inorderTraversal(TreeNode root) { - ArrayList rst = new ArrayList(); - if (root == null) { - return rst; - } - Stack stack = new Stack(); - TreeNode curr = root; - stack.push(curr); - while (!stack.empty()) { - while (curr != null && curr.left != null) { - curr = curr.left; - stack.push(curr); - } - curr = stack.pop(); - rst.add(curr.val); - curr = curr.right; - if (curr != null) { - stack.push(curr); - } - } - return rst; - } - - - -} ``` \ No newline at end of file diff --git a/Java/Binary Tree Level Order Traversal II.java b/Java/Binary Tree Level Order Traversal II.java old mode 100644 new mode 100755 index ae360e1..8380746 --- a/Java/Binary Tree Level Order Traversal II.java +++ b/Java/Binary Tree Level Order Traversal II.java @@ -1,5 +1,15 @@ +M + +普通BFS,用一个queue,加上一个queue.size()来交替换行. + +rst里面add(0,...)每次都add在list开头 + + +``` + /* -Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). +Given a binary tree, return the bottom-up level order traversal of its nodes' values. +(ie, from left to right, level by level from leaf to root). Example Given binary tree {3,9,20,#,#,15,7}, @@ -19,15 +29,7 @@ [3] ] Tags Expand -Tree Search Breadth First Search Queue Binary Tree - - -Thinking Process: -1. Non-recursive -similar to Binary Tree Level Order Traversal I, just when adding into the final result, add to the top all the time. Then the first added will be at the bottom: result.add(0, list) -2. Recursive: - Similar to Level Traversal I, do a dfs. The difference is: everytime, we use ArrayList> like a stack by doing add(0, newList); - when populating the levelArrayList, make sure to address the correct corresponding level. +Queue Binary Tree Binary Tree Traversal Breadth First Search */ /** @@ -43,6 +45,18 @@ */ + /* + +Thoughts: +1. Non-recursive +similar to Binary Tree Level Order Traversal I, just when adding into the final result, +add to the top all the time. Then the first added will be at the bottom: result.add(0, list) +2. Recursive: + Similar to Level Traversal I, do a dfs. The difference is: everytime, we use ArrayList> like a stack by doing add(0, newList); + when populating the levelArrayList, make sure to address the correct corresponding level. + + */ + public class Solution { /** * @param root: The root of binary tree. @@ -89,3 +103,4 @@ public void dfs(TreeNode root, int level, ArrayList> rst) { } } +``` diff --git a/Java/Binary Tree Level Order Traversal.java b/Java/Binary Tree Level Order Traversal.java old mode 100644 new mode 100755 index 8cdb741..aa2d884 --- a/Java/Binary Tree Level Order Traversal.java +++ b/Java/Binary Tree Level Order Traversal.java @@ -1,9 +1,16 @@ -1. 最普通,Non-recursive: bfs, queue -2. Recursive with dfs: use a level to track. Add curr into corresponding level; each level > rst.size(), add a new []. - Note: rst is a ArrayList>, where each level is a arraylist; that is why we can add [] into rst to represent a level. +M + +方法1. 最普通,Non-recursive: BFS, queue, 用个queue.size()来end for loop:换行。 + 或者用两个queue. 当常规queue empty,把backup queue贴上去。 + +方法2. Recursive with dfs: + 每个level都应该有个ArrayList. 那么用一个int level来查看:是否每一层都有了相应的ArrayList。 + 如果没有,就加上一层。 + 之后每次都通过DFS在相应的level上面加数字。 + + ``` /* -34% Accepted Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). Example @@ -24,21 +31,13 @@ [15,7] ] Challenge -Using only 1 queue to implement it. +Challenge 1: Using only 1 queue to implement it. + +Challenge 2: Use DFS algorithm to do it. Tags Expand -Tree Search Breadth First Search Queue Binary Tree +Queue Binary Tree Breadth First Search Binary Tree Traversal Uber LinkedIn Facebook -Thinking process: -1. Non-recursive -Use queue to withhold the parent. -Poll one parent, add this parent’s value to arrayList -Add the children into Arraylist -jump to next level -2. Recursive -use a integer to track levels. -If at a new level, then create a new ArrayList. -At each node, add the node to corresponding level-ArrayList */ /** @@ -53,6 +52,21 @@ * } */ +/* +Thoughts: +1. Non-recursive +Use queue to withhold the parent. +Poll one parent, add this parent’s value to arrayList +Add the children into Arraylist +jump to next level +2. Recursive +use a integer to track levels. +If at a new level, then create a new ArrayList. +At each node, add the node to corresponding level-ArrayList +*/ + +//Non-recurive Iterative way: +//Even with while + for nested loop, it's just O(n) public class Solution { /** * @param root: The root of binary tree. @@ -63,7 +77,7 @@ public ArrayList> levelOrder(TreeNode root) { if (root == null) { return result; } - /* //Non-recurive Iterative way: + //Use a queue to list elements: each row Queue queue = new LinkedList(); queue.offer(root); @@ -83,9 +97,58 @@ public ArrayList> levelOrder(TreeNode root) { } result.add(list); }//while - */ + + return result; + } +} + +//Another Iterative way: using 2 Queues +public class Solution { + public List> levelOrder(TreeNode root) { + List> rst = new ArrayList>(); + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + Queue backQueue = new LinkedList(); + queue.offer(root); + ArrayList list = new ArrayList(); + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (node.left != null) { + backQueue.offer(node.left); + } + if (node.right != null) { + backQueue.offer(node.right); + } + list.add(node.val); + + if (queue.isEmpty()) { + rst.add(new ArrayList(list)); + list = new ArrayList(); + queue = backQueue; + backQueue = new LinkedList(); + } + + } + return rst; + } +} + + + +//Recursive: +//Recursive with dfs: use a level to track. Add curr into corresponding level; each level > rst.size(), add a new []. +//Note: rst is a ArrayList>, where each level is a arraylist; that is why we can add [] into rst to represent a level. + +public class Solution { + public ArrayList> levelOrder(TreeNode root) { + ArrayList> result = new ArrayList>(); + if (root == null) { + return result; + } - //Recursive: dfs(root, 0, result); return result; } diff --git a/Java/Binary Tree Longest Consecutive Sequence.java b/Java/Binary Tree Longest Consecutive Sequence.java new file mode 100644 index 0000000..37793fe --- /dev/null +++ b/Java/Binary Tree Longest Consecutive Sequence.java @@ -0,0 +1,129 @@ +M + +屌炸天的4行代码。Divide and Conquer + +主要想法: +Recursive用好。首先在这个level比一比,可否成。 +不成的话,另立门户, count = 1。 +然后左右开弓。再把结果拿过来比较一下就好了。 + +``` +/* +Given a binary tree, find the length of the longest consecutive sequence path. + +The path refers to any sequence of nodes from some starting node to any node in the tree +along the parent-child connections. The longest consecutive path need to be from parent to child +(cannot be the reverse). + +For example, + 1 + \\ + 3 + / \\ + 2 4 + \\ + 5 +Longest consecutive sequence path is 3-4-5, so return 3. + 2 + \\ + 3 + / + 2 + / + 1 +Longest consecutive sequence path is 2-3,not3-2-1, so return 2. + +Tags:Tree +Similar Problems: (H) Longest Consecutive Sequence + +*/ + +/* +Attemp2: http://www.cnblogs.com/jcliBlogger/p/4923745.html. +The original solution has just 4 lines of C++ code. That hurts. +The concept is very much similar as my attempt1, though the code is more clear with recursive call +1. pass alone a depth. +2. if consecutive, depth++; else, start from depth 1 +3. Go deeper on both left, and right; both with new depth: currDepth; +4. Compare the Max of currDept, left's return, right's return. +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public int longestConsecutive(TreeNode root) { + return recursiveHelper(root, null, 0); + } + + public int recursiveHelper(TreeNode curr, TreeNode parent, int depth) { + if (curr == null) { + return 0; + } + int currDepth = 0; + if (parent != null && parent.val + 1 == curr.val) { + currDepth = depth + 1; + } else { + currDepth = 1; + } + return Math.max(currDepth, Math.max(recursiveHelper(curr.left, curr, currDepth), recursiveHelper(curr.right, curr, currDepth))); + } +} + + +/* +Attemp1, failed. +Thoughts: +Seems like backtracking: we find the lowest level, then return depth, and add it on parent's record if consectutive. +always record a max value. +If node.left != null || node.right != null, if consecutive, node.depth = node.child.depth +1 +If node.left == null && node.right == null, return 1; + + +public class Solution { + private int max = Integer.MIN_VALUE; + public int longestConsecutive(TreeNode root) { + dfsOnNode(root); + return max; + } + + public int dfsOnNode(TreeNode root) { + int depth = 0; + int localMax = Integer.MIN_VALUE; + if (root == null) { + return depth; + } + if (root.left == null && root.right == null) {//ON:right4, + depth++; + return depth; + } + if (root.right != null) {//root.right = 3, right4, + int childDepth = longestConsecutive(root.right);//ON: 3, right4 + if (root.val + 1 == root.right.val) {//3+1=4 + depth = childDepth + 1;//1+1=2 + } else { + depth = 1; + } + } + localMax = Math.max(localMax, depth); + if (root.left != null) { + int childDepth = longestConsecutive(root.left); + if (root.val + 1 == root.left.val) { + depth = childDepth + 1; + } else { + depth = 1; + } + } + localMax = Math.max(localMax, depth); + max = Math.max(max, localMax); + return localMax; + } +} +*/ +``` \ No newline at end of file diff --git a/Java/Binary Tree Maximum Path Sum II.java b/Java/Binary Tree Maximum Path Sum II.java index 0dbb7b8..3535f3b 100644 --- a/Java/Binary Tree Maximum Path Sum II.java +++ b/Java/Binary Tree Maximum Path Sum II.java @@ -1,7 +1,15 @@ -比Binary Tree Maximum Path Sum I 简单许多. -因为条件给的更多:at least 1 node + have to start from root => have to have root. -Single path: either left or right. -If the path sum < 0, just skip it. +M + +比Binary Tree Maximum Path Sum I 简单许多. 因为条件给的更多:at least 1 node + have to start from root => have to have root. + +方法1: +维持一个global或者recursive里的sum。traversal entire tree via DFS. 简单明了。 + + +方法2: +Single path: either left or right. +If the path sum < 0, just skip it. + ``` /* Binary Tree Maximum Path Sum II @@ -22,6 +30,29 @@ Binary Tree */ +/* + 02.20.2016 recap + just return integer sum, so just traversal the entier binary tree via dfs + dfs: node, sum, return sum +*/ +public class Solution { + public int maxPathSum2(TreeNode root) { + if (root == null) { + return 0; + } + return dfs(root, 0); + } + public int dfs (TreeNode node, int sum) { + if (node == null) { + return sum; + } + sum += node.val; + return Math.max(sum, Math.max(dfs(node.left, sum), + dfs(node.right, sum))); + } +} + + /* Thoughts: maximum path sum from root, so it must include root, and it will be a single path from root to some point in the tree. @@ -29,17 +60,6 @@ 'contains at least 1 node' -> at least have root. However, depending on child is positive or negative, we choose add or no add child */ -/** - * Definition of TreeNode: - * public class TreeNode { - * public int val; - * public TreeNode left, right; - * public TreeNode(int val) { - * this.val = val; - * this.left = this.right = null; - * } - * } - */ public class Solution { /** * @param root the root of binary tree. diff --git a/Java/Binary Tree Maximum Path Sum.java b/Java/Binary Tree Maximum Path Sum.java index f3ad82e..ade8d5e 100644 --- a/Java/Binary Tree Maximum Path Sum.java +++ b/Java/Binary Tree Maximum Path Sum.java @@ -1,37 +1,43 @@ -有点难理解. -复杂原因是:因为可能有负值啊。不能乱assume正数。 -single path max 的计算是为了给后面的comboMax用的。 -如果single path max小于0,那没有什么加到parent上面的意义,所以就被再次刷为0. -combo的三种情况:(root可能小于0)1. 只有left, 2。 只有右边。 3. root大于0,那么就left,right,curr全部加起来。 - 情况1和情况2去一个最大值, - 然后和情况三比较。 - 做了两个Math.max(). 然后就有了这一层的comboMax - - -12.11.2015 recap: - So totally, 5 conditions: - (save in single:) - left + curr.val - right + curr.val - (save in combo:) - left, - right, - left + curr.val + right +M + +第一次做有点难理解,复杂原因是:因为可能有负值啊。不能乱assume正数。 + single path max 的计算是为了给后面的comboMax用的。 + 如果single path max小于0,那没有什么加到parent上面的意义,所以就被再次刷为0. + +combo的三种情况:(root可能小于0) + 1. 只有left + 2。 只有右边 + 3. root大于0,那么就left,right,curr全部加起来。 + +情况1和情况2取一个最大值,然后和情况三比较。做了两个Math.max(). 然后就有了这一层的comboMax + + +12.11.2015 recap: + So totally, 5 conditions: + (save in single) + left + curr.val OR right + curr.val + (save in combo:) + left, right, OR left + curr.val + right + ``` /* -23% Accepted Given a binary tree, find the maximum path sum. + The path may start and end at any node in the tree. + + Example -Given the below binary tree, - 1 - / \ - 2 3 -Return 6. +Given the below binary tree: + + 1 + / \ +2 3 +return 6. + Tags Expand -Dynamic Programming Tree Depth First Search +Divide and Conquer Dynamic Programming Recursion */ @@ -95,8 +101,9 @@ public PathSumType helper(TreeNode root) { int singlePathMax = Math.max(left.singlePathMax, right.singlePathMax) + root.val; singlePathMax = Math.max(singlePathMax, 0);//If less than 0, no need to keep, because it only decrease parent-level max. - //first comparison: does not include curr node at all(this would be applicable when curr.val < 0, so we take this condition into account) + //first comparison: does not include root node at all(this would be applicable when curr.val < 0, so we take this condition into account) int combinedPathMax = Math.max(left.combinedPathMax, right.combinedPathMax); + //second comparison: combinedPathMax = Math.max(combinedPathMax, left.singlePathMax + right.singlePathMax + root.val); return new PathSumType(singlePathMax, combinedPathMax); diff --git a/Java/Binary Tree Path Sum.java b/Java/Binary Tree Path Sum.java index 9e8bfbc..02a05a7 100644 --- a/Java/Binary Tree Path Sum.java +++ b/Java/Binary Tree Path Sum.java @@ -1,6 +1,11 @@ -Binary Tree的一个基本题。 -遍历到底,比较sum vs. target。 -注意divde的情况。起码要把遍历的例子写写。 +E + +Binary Tree的一个基本题。 +遍历到底,比较sum vs. target。 +注意divide的情况。要把遍历的例子写写。 + +LeetCode: Path Sum II + ``` /* Given a binary tree, find all paths that sum of the nodes in the path equals to a given number target. @@ -44,6 +49,40 @@ * } */ +/* +3.1.2016 Recap +Same approach +*/ +public class Solution { + public List> pathSum(TreeNode root, int sum) { + List> rst = new ArrayList>(); + if (root == null) { + return rst; + } + dfs(rst, new ArrayList(), root, 0, sum); + + return rst; + } + + public void dfs(List> rst, ArrayList list, TreeNode node, int add, int sum) { + list.add(node.val); + if (node.left == null && node.right == null) { + if (add + node.val == sum) { + rst.add(new ArrayList(list)); + } + return; + } + if (node.left != null) { + dfs(rst, list, node.left, add + node.val, sum); + list.remove(list.size() - 1); + } + if (node.right != null) { + dfs(rst, list, node.right, add + node.val, sum); + list.remove(list.size() - 1); + } + } +} + public class Solution { public List> binaryTreePathSum(TreeNode root, int target) { List> rst = new ArrayList>(); diff --git a/Java/Binary Tree Paths.java b/Java/Binary Tree Paths.java index f2e8730..f15a24c 100644 --- a/Java/Binary Tree Paths.java +++ b/Java/Binary Tree Paths.java @@ -1,7 +1,13 @@ +E + +方法1: Recursive:分叉。Helper。 -非递归练习了一下 -因为要每次切短list, 所以再加了一个Stack 来存level +方法2,Iterative: + 非递归练习了一下 + 因为要每次切短list, 所以再加了一个Stack 来存level + + ``` /* Binary Tree Paths @@ -127,10 +133,6 @@ public List binaryTreePaths(TreeNode root) { return rst; } } - - - - /** * Definition of TreeNode: * public class TreeNode { diff --git a/Java/Binary Tree Postorder Traversal.java b/Java/Binary Tree Postorder Traversal.java old mode 100644 new mode 100755 index 795367c..68ed22d --- a/Java/Binary Tree Postorder Traversal.java +++ b/Java/Binary Tree Postorder Traversal.java @@ -1,9 +1,11 @@ -最prefer 2 stack的做法。特别清楚。 -stack1和stack2合作。 -记得这个做法。。。挺神奇的。 +E -Divide and Conquer 的方法也非常明了! +最prefer 2 stack的做法: + stack1和stack2合作。倒水。记这个做法。。。挺神奇的。 +Divide and Conquer 的recursive方法也非常明了! + +注意,这些binary tree traversal的题目,常常有多个做法:recursive or iterative ``` /* @@ -63,7 +65,7 @@ public ArrayList postorderTraversal(TreeNode root) { /* - 2. Non-recursive, interative + 2. Non-recursive, iterative use 2 stacks: pull water from s1 into s2 in s2, we want: at each level, parentNode at bottom, then rightNode, then leftNode loop through s2, then we print out leftNode, rightNode, parentNode ... in postOrder. @@ -132,11 +134,4 @@ public void helper(ArrayListrst, TreeNode node) { } - - - - - - - ``` \ No newline at end of file diff --git a/Java/Binary Tree Preorder Traversal.java b/Java/Binary Tree Preorder Traversal.java old mode 100644 new mode 100755 index f2cc535..1fb121f --- a/Java/Binary Tree Preorder Traversal.java +++ b/Java/Binary Tree Preorder Traversal.java @@ -1,7 +1,10 @@ -Preorder 写写, stack -1. Divide and conquer -2. Stack(NON-recursive) push curr, push right, push left. -3. recursive with helper method +E + +Preorder 写写, stack +1. Divide and conquer +2. Stack(NON-recursive) push curr, push right, push left. +3. recursive with helper method + ``` /* Given a binary tree, return the preorder traversal of its nodes' values. diff --git a/Java/Binary Tree Right Side View.java b/Java/Binary Tree Right Side View.java new file mode 100644 index 0000000..a599bbd --- /dev/null +++ b/Java/Binary Tree Right Side View.java @@ -0,0 +1,131 @@ +M + +最右:即level traversal每一行的最末尾. + +BFS,用queue.size()来出发saving result. + +``` +/* +Given a binary tree, imagine yourself standing on the right side of it, +return the values of the nodes you can see ordered from top to bottom. + +For example: +Given the following binary tree, + 1 <--- + / \\ +2 3 <--- + \\ \\ + 5 4 <--- +You should return [1, 3, 4]. + +Tags: Tree, Depth-first Search, Breadth-first Search +Similar Problems: (M) Populating Next Right Pointers in Each Node + +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +/* +02.09.2016 Revist +Thoughts: +BFS: traverse all levels, save to ArrayList, get all nodes at end of level list. +*/ + +public class Solution { + public List rightSideView(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + queue.offer(root); + int size = queue.size(); + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + size--; + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + if (size == 0) { + rst.add(node.val); + size = queue.size(); + } + } + + return rst; + } +} + + +/* + +自己想了这个方法,有可能不是特别efficient. +一个queue放普通的BFS。 +一个queue放level。 +同时维护一个parent value;维护一个跟着BFS跑的level。 +每个node都有一个lv。一旦lv和正在跑的level不一样,证明lv>level,那么也就是说,刚刚换行拉。parent的值,就是上一行最右边的值。DONE. + + +Thoughts: +Use 2 queue: one for BFS, one for level. Each node in queue has a corresponding level +Track level. +WHen level != levelQ.poll(), that means we are moving to next level, and we should record the previous(parent) node's value. +*/ + +public class Solution { + public List rightSideView(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + Queue q = new LinkedList(); + Queue levelQ = new LinkedList(); + q.offer(root); + levelQ.offer(1); + int level = 1; + int parent = root.val; + TreeNode node = null; + + while (!q.isEmpty()) { + node = q.poll(); + int lv = levelQ.poll(); + if (level != lv) { + level++; + rst.add(parent); + } + parent = node.val; + if (node.left != null) { + q.offer(node.left); + levelQ.offer(lv + 1); + } + if (node.right != null) { + q.offer(node.right); + levelQ.offer(lv + 1); + } + }//END while + rst.add(parent); + return rst; + } +} + + + + + + + + + + +``` \ No newline at end of file diff --git a/Java/Binary Tree Serialization.java b/Java/Binary Tree Serialization.java new file mode 100644 index 0000000..ca94852 --- /dev/null +++ b/Java/Binary Tree Serialization.java @@ -0,0 +1,182 @@ +M + +方法1: BFS. Non-recursive, using queue. 想法直观。level-order traversal. save到一个string里面就好。 + +方法2: DFS. Recursive. 需要一点思考。basically divide and conquer. 但是代码相对来说短。 + +``` + +/* +Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'. + +There is no limit of how you deserialize or serialize a binary tree, you only need to make sure you can serialize a binary tree to a string and deserialize this string to the original structure. + +Have you met this question in a real interview? Yes +Example +An example of testdata: Binary tree {3,9,20,#,#,15,7}, denote the following structure: + + 3 + / \ +9 20 + / \ + 15 7 +Our data serialization use bfs traversal. This is just for when you got wrong answer and want to debug the input. + +You can use other method to do serializaiton and deserialization. + +Tags Expand +Binary Tree Microsoft Yahoo + +*/ + + + //BFS. store as string, separated by ',' +//Note: need to record null node as well. but be careful don't push null into queue +class Solution { + /** + * This method will be invoked first, you should design your own algorithm + * to serialize a binary tree which denote by a root node to a string which + * can be easily deserialized by your own "deserialize" method later. + */ + public String serialize(TreeNode root) { + String rst = ""; + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + queue.offer(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode node = queue.poll(); + if (node.val == Integer.MIN_VALUE) { + rst += "#,"; + } else { + rst += node.val + ","; + TreeNode left = node.left == null ? + new TreeNode(Integer.MIN_VALUE) : node.left; + queue.offer(left); + TreeNode right = node.right == null ? + new TreeNode(Integer.MIN_VALUE) : node.right; + queue.offer(right); + } + } + } + return rst; + } + + /** + * This method will be invoked second, the argument data is what exactly + * you serialized at method "serialize", that means the data is not given by + * system, it's given by your own serialize method. So the format of data is + * designed by yourself, and deserialize it here as you serialize it in + * "serialize" method. + */ + public TreeNode deserialize(String data) { + if (data == null || data.length() == 0) { + return null; + } + TreeNode root = new TreeNode(0); + root.val = Integer.parseInt(data.substring(0, data.indexOf(","))); + data = data.substring(data.indexOf(",") + 1); + + Queue queue = new LinkedList(); + queue.offer(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode node = queue.poll(); + String temp = data.substring(0, data.indexOf(",")); + if (!temp.equals("#")) { + node.left = new TreeNode(Integer.parseInt(temp)); + queue.offer(node.left); + } + data = data.substring(data.indexOf(",") + 1); + + temp = data.substring(0, data.indexOf(",")); + if (!temp.equals("#")) { + node.right = new TreeNode(Integer.parseInt(temp)); + queue.offer(node.right); + } + data = data.substring(data.indexOf(",") + 1); + } + } + + return root; + } +} + + + + + + + + + + + + +//DFS approach, recursive + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +class Solution { + /** + * This method will be invoked first, you should design your own algorithm + * to serialize a binary tree which denote by a root node to a string which + * can be easily deserialized by your own "deserialize" method later. + */ + public String serialize(TreeNode root) { + if (root == null) { + return "#,"; + } + String mid = root.val + ","; + String left = serialize(root.left); + String right = serialize(root.right); + mid += left + right; + return mid; + } + + private String data = ""; + /** + * This method will be invoked second, the argument data is what exactly + * you serialized at method "serialize", that means the data is not given by + * system, it's given by your own serialize method. So the format of data is + * designed by yourself, and deserialize it here as you serialize it in + * "serialize" method. + */ + public TreeNode deserialize(String data) { + this.data = data; + return desHelper(); + } + + public TreeNode desHelper() { + if (this.data.indexOf("#,") == 0) { + this.data = this.data.substring(this.data.indexOf(",") + 1); + return null; + } + String midVal = this.data.substring(0, this.data.indexOf(",")); + TreeNode mid = new TreeNode(Integer.parseInt(midVal)); + this.data = this.data.substring(this.data.indexOf(",") + 1); + TreeNode left = desHelper(); + TreeNode right = desHelper(); + mid.left = left; + mid.right = right; + return mid; + } +} + + +``` \ No newline at end of file diff --git a/Java/Binary Tree Zigzag Level Order Traversal.java b/Java/Binary Tree Zigzag Level Order Traversal.java old mode 100644 new mode 100755 index fda05d8..9110727 --- a/Java/Binary Tree Zigzag Level Order Traversal.java +++ b/Java/Binary Tree Zigzag Level Order Traversal.java @@ -1,5 +1,11 @@ -/* 24% Accepted -Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). +M + +简单的level traversal.根据level奇数偶数而add到不同位子. + +``` +/* +Given a binary tree, return the zigzag level order traversal of its nodes' values. +(ie, from left to right, then right to left for the next level and alternate between). Example Given binary tree {3,9,20,#,#,15,7}, @@ -21,11 +27,6 @@ Tags Expand Tree Search Breadth First Search Queue Binary Tree -Thinking Process: -1. realize: queue is no longer can be used. draw a example map to see why. -Instead, use 2 stacks. -Because we can only take the top of stack, and we are constantly adding to the top of the stac, so we need 2 stacks. One is the current one, will be empty every time when we finish the level. The other one is nextLevel, which holds next level’s nodes temporarily. -2. Use a boolean to track if which level it’s running at. */ /** @@ -39,8 +40,60 @@ * } * } */ + + +//Recap 02.23.2015. BFS. first level = 0; level % 2 = 1, list.add(0, ...) +public class Solution { + /** + * @param root: The root of binary tree. + * @return: A list of lists of integer include + * the zigzag level order traversal of its nodes' values + */ + public ArrayList> zigzagLevelOrder(TreeNode root) { + ArrayList> rst = new ArrayList>(); + if (root == null) { + return rst; + } + + int level = 0; + int size = 0; + Queue queue = new LinkedList(); + queue.offer(root); + + while (!queue.isEmpty()) { + size = queue.size(); + ArrayList list = new ArrayList(); + for (int i = 0 ; i < size; i++) { + TreeNode node = queue.poll(); + if (level % 2 == 0) { + list.add(node.val); + } else { + list.add(0, node.val); + } + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } + level++; + rst.add(list); + } + + return rst; + + } +} + /* +Thought: +1. realize: queue is no longer can be used. draw a example map to see why. +Instead, use 2 stacks. +Because we can only take the top of stack, and we are constantly adding to the top of the stac, so we need 2 stacks. One is the current one, will be empty every time when we finish the level. The other one is nextLevel, which holds next level’s nodes temporarily. +2. Use a boolean to track if which level it’s running at. + */ public class Solution { /** * @param root: The root of binary tree. @@ -89,3 +142,5 @@ public void addLevel(Stack level, TreeNode node) { } } + +``` \ No newline at end of file diff --git a/Java/Building Outline.java b/Java/Building Outline.java old mode 100644 new mode 100755 index 994b2b6..9c270cb --- a/Java/Building Outline.java +++ b/Java/Building Outline.java @@ -1,6 +1,29 @@ +H + +又叫做skyline + +看网上的解答做, 思路很漂亮。 (http://codechen.blogspot.com/2015/06/leetcode-skyline-problem.html?_sm_au_=isVmHvFmFs40TWRt) + +跟scan line的approach类似: +1. 把所有点分出来, 每个点有index x, 再加上一个height. +2. 在这个list上排序,根据index和height(注意用负数标记building start point,这样保证start在end 之前。). 叫做 heightPoints +3. 在processs时候用max-heap (reversed priorityqueue),在ieteraete heightPoints 来存最大的height . 遇到peek,就是一个合理的解 + 处理1:因为start,end的height都存在了heightPoints里面,这里就是用来check end of bulding的,然后把height 从queue里面remove. + 处理2:重复x 上面的许多height? priorityqueue给了我们最高,这okay了;那么其他的重复点,用一个int prev来mark之前做过的,一旦重复,跳过。 + +想法非常natural。 大题目,脑子乱。 +看了解答再去想,挺naturally doable的。 + +``` /* -Given N buildings in a x-axis,each building is a rectangle and can be represented by a triple (start, end, height),where start is the start position on x-axis, end is the end position on x-axis and height is the height of the building. Buildings may overlap if you see them from far away,find the outline of them。 -An outline can be represented by a triple, (start, end, height), where start is the start position on x-axis of the outline, end is the end position on x-axis and height is the height of the outline. +LintCode description: +Given N buildings in a x-axis,each building is a rectangle and can be represented by a triple (start, end, height), +where start is the start position on x-axis, end is the end position on x-axis and height is the height of the building. +Buildings may overlap if you see them from far away,find the outline of them。 +An outline can be represented by a triple, (start, end, height), +where start is the start position on x-axis of the outline, +end is the end position on x-axis and height is the height of the outline. + Example Given 3 buildings: [ @@ -19,32 +42,114 @@ Tags Expand LintCode Copyright Heap */ + +/*LeetCode description +A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B). + + Buildings Skyline Contour +The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0. + +For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] . + +The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour. + +For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]. + +Notes: + +The number of buildings in any input list is guaranteed to be in the range [0, 10000]. +The input list is already sorted in ascending order by the left x position Li. +The output list must be sorted by the x position. +There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...] + +Hide Tags Divide and Conquer Binary Indexed Tree Heap Segment Tree + +*/ + /* -Thoughts: -Well, based on JiuZhang, http://www.jiuzhang.com/solutions/building-outline/, implement a HashHeap. -**HashHeap. Super long implementation: http://www.jiuzhang.com/solutions/hash-heap/ + Thoughts + Based idea here:http://codechen.blogspot.com/2015/06/leetcode-skyline-problem.html?_sm_au_=isVmHvFmFs40TWRt + Here is the thinking process, 3.15.2016 + + The class HeightPoint{int x, int height} is very similar to scan line Point{int x, int flag}. However the usage is a bit different. + Sort all of the heightPoints by index && by height. + Use nagtive height for start point to make sure start appears before end point, tho they share same height + We use an extra priorityQueue to store the height being processed (note, this queue, decending order, max in front) + When having a negative height(start point), add into queue + At each point, find heightest point (common sense!) and mark it on map: the overlapping point at this index will be skipped because the rest are not high enough. + How to process the rest redundant point? + Here introduce a 'prev' variable that stores last processed value. If same height appears right before curr, don't add to result; it's added during this continuous line. + How to maintain the queue? + Once a height > 0 appears, remove that height from queue. + OKay, let's break it down: + because we sort HeightPoint object by index and height, start height will appear before end height of same building, for sure. + So whenever positive height appears, the same bulding must have been marked, so can safely remove the height instance from queue. + Well, in HeightPoint object, start height is negative for sorting purpose. When adding into queue, use it's absolute value : ) */ +public class Solution { + public class HeightPoint{ + int x, height; + public HeightPoint(int x, int height) { + this.x = x; + this.height = height; + } + } + public List getSkyline(int[][] buildings) { + List rst = new ArrayList(); + if (buildings == null || buildings.length == 0 || buildings[0].length == 0) { + return rst; + } + //Init the list sorted by index && height + List heightPoints = new ArrayList(); + for (int i = 0; i < buildings.length; i++) { + heightPoints.add(new HeightPoint(buildings[i][0], -buildings[i][2])); + heightPoints.add(new HeightPoint(buildings[i][1], buildings[i][2])); + } + Collections.sort(heightPoints, new Comparator() { + public int compare(HeightPoint p1, HeightPoint p2) { + if (p1.x == p2.x) { + return p1.height - p2.height; + } else { + return p1.x - p2.x; + } + } + }); + //Process height points + //reversed priorityqueue, becase for same pos x, we always want the highest point + PriorityQueue queue = new PriorityQueue(1000, Collections.reverseOrder()); + queue.offer(0); + int prev = queue.peek(); + for (HeightPoint p : heightPoints) { + if (p.height < 0) { + queue.offer(-p.height); + } else { + queue.remove(p.height); + } + int currPeak = queue.peek(); + if (currPeak != prev) { + rst.add(new int[] {p.x, currPeak}); + prev = currPeak; + } + } -/**** - Attempt1, may not be correct. - Thoughts: - PriorityQueue, sort by start. - 1. Keep track of max height. - 2. Find max height. - 3. Poll() queue. Whenever there is a jump(up or down) at current node, close a interval. - 4. When closing interval, set prev = new node.h -****/ + return rst; + } +} -/** + +/* +Thoughts: +Well, based on JiuZhang, http://www.jiuzhang.com/solutions/building-outline/, implement a HashHeap. +**HashHeap. Super long implementation: http://www.jiuzhang.com/solutions/hash-heap/ What is HashHeap Exactly? Document below: -**/ +*/ class HashHeap { //Heap is a arraylist, which stores the actaul Integer values. It stores the real data ArrayList heap; @@ -227,3 +332,5 @@ void siftdown(int id) { } } } + +``` \ No newline at end of file diff --git a/Java/Burst Balloons.java b/Java/Burst Balloons.java new file mode 100644 index 0000000..ec05ba9 --- /dev/null +++ b/Java/Burst Balloons.java @@ -0,0 +1,121 @@ +其实会做之后挺好想的一个DP。 +dp[i][j] = balloons i~j 之间的sum. 然后找哪个点开始burst? 设为x。 +For loop 所有的点作为x, 去burst。 +每次burst都切成了三份:左边可以recusive 求左边剩下的部分的最大值 + 中间3项相乘 + 右边递归下去求最大值。 + + +这个是momorization, 而不纯是DP +因为recursive了,其实还是搜索,但是memorize了求过的值,节省了Processing +``` +/* +Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. +You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. +Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent. + +Find the maximum coins you can collect by bursting the balloons wisely. + +Note: +(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them. +(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 + +Example: + +Given [3, 1, 5, 8] + +Return 167 + + nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] + coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 +Credits: +Special thanks to @peisi for adding this problem and creating all test cases. + +Hide Company Tags Google +Show Tags +Divide and Conquer Dynamic Programming + + +*/ + +/* + Thoughts: as seen in dicussion. Build DP. + State: + dp[i][j]: the number of max coins can collect between i and j. + For a position x in [i,j], where to burst it? So this goes into a divide and conquer method. + Burst at x, track the sum, and record the max into dp[i][j] + Function: + dp[i][j] = Math.max(dp[i][j], DP(i, x-1) + nums[x-1]*nums[x]*nums[x+1] + DP(x+1, j)) + Init: + create dp[n+2][n+2]. (from 0 to n+1) + dp[0][1] = 1; + dp[n][n+1] = 1; + Return: + dp[1][n] + + DP(int i, int j, int[][] dp) + + Need to redo that nums. +*/ + + +public class Solution { + int[][] dp; + int[] values; + public int maxCoins(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int n = nums.length; + dp = new int[n + 2][n + 2]; + + //Initialize new array + values = new int[n + 2]; + values[0] = values[n + 1] = 1; + for (int i = 1; i < n + 1; i++) { + values[i] = nums[i - 1]; + } + + return DP(1, n); + } + + public int DP(int i, int j){ + if (dp[i][j] > 0) {//momorization + return dp[i][j]; + } + for (int x = i; x <= j; x++) { + dp[i][j] = Math.max(dp[i][j], DP(i, x - 1) + values[i-1]*values[x]*values[j+1] + DP(x + 1, j)); + } + return dp[i][j]; + } +} + +/* + 用了recursive + memorization, 但是也可以用传统的DP,比如: + for (int length = 1; length < n; length++) [ + for (int = 0; i < n-1; i++) { + j = i + length; + if length == 1: + dp[i][j] = A[i] * A[j] + A[i] + else: + dp[i][j] = max {} + } + } + +*/ + + + +/* + My Thought: TOO COMPLEX. Should go with the easy DP approach. Also, using a hashMap to trach all the patterns, + this might not be applicable: because as the integer array's length goes up, there will be too many possible + combinations to store in hashamp. + Burst each balloon, and DFS into each branch, calcualte the sum + each balloon-burst's product. + Also, use a HahsMap<"Value combination", max value>. to reduce the # of re-calculation. + convert nums into string, and in DFS, we don't even need bakc-tracking + helper(list, sum) + + + Thoughts:http://www.cnblogs.com/grandyang/p/5006441.html + dp[i,j]: burst range [i~j]'s max coins. + +*/ +``` diff --git a/Java/Change to Anagram.java b/Java/Change to Anagram.java new file mode 100755 index 0000000..121f7db --- /dev/null +++ b/Java/Change to Anagram.java @@ -0,0 +1,103 @@ +E + +简单的check int[26] 26个小写字母是否需要改变。若需要count+1. + +主要HackerRank里要注意自己写: Scanner, import java.util, non-static method ...etc. + +注意: 最后count出来要除以2:字母不同,会在不同的字母位上加减count,那么就是刚好重复计算了一遍。所以除以二。 + +``` +/* +HackerRank CodePair + +Sid loves to read short stories. Being a Computer Science student, he decides to do some frequency analysis on his favorite reading material. For each data point, chooses a string of length a from one book, and a string of length b from a second book. The strings' lengths differ by no more than 1. +|a-b|≤1, where |x| represents the absolute value function. + +The frequency analysis consists of checking how far the strings are from being anagrams of one another. Your challenge is to help him find the minimum number of characters of the first string he needs to change to make it an anagram of the second string. He can neither add nor delete characters from the first string. Only replacement of the characters with new ones is allowed. + +Input Format +The first line will contain an integer T representing the number of test cases. Each test case will contain a string having length (a+b) which will be concatenation of both the strings described in problem. The string will only contain small letters and without any spaces. + +Output Format +An integer corresponding to each test case is printed in a different line i.e., the number of changes required for each test case. Print ‘-1’ if it is not possible. + +Constraints +1 ≤ T ≤ 100 + 1 ≤ a+b ≤ 10,000 + +Sample Input +5 +aaabbb +ab +abc +mnop +xyyx +Sample Output +3 +1 +-1 +2 +0 + +Explanation +In the five test cases +One string must be “aaa” and the other “bbb”. The lengths are a=3 and b=3, so the difference is less than 1. No characters are common between the strings, so all three must be changed. +One string must be “a” and the second “b”. The lengths are a=1 and b=1, so the difference is less than 1. One character must be changed to them the same. +Since the string lengths a and b must differ by no more than 1, the lengths are either a=1 and b=2 or a=2 and b=1. No sequence of substitutions will make the two anagrams of one another. +One string must be “mn" and other be “op”. The length are a=2 and b=2, so the difference is less than 1. No characters are common between the strings, so both must be changed. +One string must be “xy” and the other be “yx”. The length are a=2 and b=2, so the difference is less than 1. No changes are needed because the second string is already an anagram of the first. +*/ + + +/* +Check if they are valid string. If length == odd, then fail, -1 +Use int[26] arr to add chars from s1. If non-26-char exist, return -1 +use same int arr to remove chars from s2. +count the non-zeros + +Note: the order of letters does not matter, becase all we want to change to is anagram +*/ +import java.io.*; +import java.util.*; +public class Solution { + public static void main(String args[] ) throws Exception { + /* Enter your code here. Read input from STDIN. Print output to STDOUT */ + Scanner in = new Scanner(System.in); + int numOfCase = Integer.parseInt(in.nextLine()); + Solution sol = new Solution(); + + while (numOfCase > 0) { + int rst = sol.validate(in.nextLine()); + System.out.println(rst); + numOfCase--; + } + } + + public int validate(String str) { + if (str.length() % 2 == 1) { + return -1; + } + String sA = str.substring(0, str.length()/2); + String sB = str.substring(str.length()/2); + + int[] arr = new int[26]; + for (int i = 0; i < sA.length(); i++) { + char cA = sA.charAt(i); + char cB = sB.charAt(i); + if (cA < 'a' || cA > 'z' || cB < 'a' || cB > 'z') { + return -1; + } + arr[cA - 'a']++; + arr[cB - 'a']--; + } + + int count = 0; + for (int num : arr) { + count += Math.abs(num); + } + return count/2; + } + + +} +``` \ No newline at end of file diff --git a/Java/Classical Binary Search.java b/Java/Classical Binary Search.java index cae325c..b4e7f42 100644 --- a/Java/Classical Binary Search.java +++ b/Java/Classical Binary Search.java @@ -1,5 +1,14 @@ +E + + while: start + 1 < end + mid = start + (end - start) / 2; + 末尾double check start, end. + + +``` /* -Find any position of a target number in a sorted array. Return -1 if target does not exist. +Find any position of a target number in a sorted array. +Return -1 if target does not exist. Example Given [1, 2, 2, 4, 5, 5]. @@ -28,25 +37,26 @@ public class Solution { * @return an integer */ public int findPosition(int[] A, int target) { - if (A == null || A.length == 0) { - return -1; - } - int start = 0; - int end = A.length - 1; - int mid; - while(start + 1 < end) { - mid = start + (end - start) / 2; - if (target == A[mid]) { - return mid; - } else if (target > A[mid]) { - start = mid; - } else { - end = mid; - } - }//end while - if (A[start] == target || A[end] == target) { - return A[start] == target ? start : end; - } - return -1; + if (A == null || A.length == 0) { + return -1; + } + int start = 0; + int end = A.length - 1; + int mid; + while(start + 1 < end) { + mid = start + (end - start) / 2; + if (target == A[mid]) { + return mid; + } else if (target > A[mid]) { + start = mid; + } else { + end = mid; + } + }//end while + if (A[start] == target || A[end] == target) { + return A[start] == target ? start : end; + } + return -1; } } +``` diff --git a/Java/Climbing Stairs.java b/Java/Climbing Stairs.java old mode 100644 new mode 100755 index 254d0b9..2fe4a33 --- a/Java/Climbing Stairs.java +++ b/Java/Climbing Stairs.java @@ -1,25 +1,119 @@ +E + +方法1: DP。爬坡到i点总共有的方法,取决于i-1点和i-2的情况。也就是DP(i-1) + DP(i-2). + +还可以用滚动数组优化一点:因为用到的变量就只有i,i-1,i-2,可以被替代。 + 注意要写好‘滚动’的代码。 + +方法2: DFS但是timeout + +``` /* -40% Accepted + You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? -Example -Tags Expand +Dynamic Programming + +*/ + +/* + 3.25.2016 recap DP + DP[i] is dependent on wether it was reached by 2 steps or just 1 step: + DP[i] = DP[i - 1] + DP[i - 2] +*/ +public class Solution { + public int climbStairs(int n) { + if (n == 0) { + return 0; + } + if (n == 1) { + return 1; + } + int[] DP = new int[n + 1]; + DP[0] = 1; + DP[1] = 1; + for (int i = 2; i <= n; i++) { + DP[i] = DP[i - 1] + DP[i - 2]; + } + return DP[n]; + } +} + +/* + Based on the DP solution, think about rolling array. + We only make use of i, i-1, and i-2. + Ideally, we can reduce them just to 3 variables + + 1. Replace the variable + 2. Implement the rotation process: + prev2 = prev1; + prev1 = rst; +*/ +public class Solution { + public int climbStairs(int n) { + if (n == 0) { + return 0; + } + if (n == 1) { + return 1; + } + int rst = 0; + int prev2 = 1; + int prev1 = 1; + for (int i = 2; i <= n; i++) { + rst = prev1 + prev2; + prev2 = prev1; + prev1 = rst; + } + return rst; + } +} + +/* + Recap 3.25.2016 + Naturally think of dfs. Any time when n drops to <= 0, count++ + Exceed time limit +*/ + +public class Solution { + public int count = 0; + public int climbStairs(int n) { + if (n <= 0) { + return 0; + } + dfs(n); + return count; + } + + public void dfs(int n) { + if (n <= 0) { + count++; + return; + } else if (n == 1) { + count++; + return; + } + dfs(n - 1); + dfs(n - 2); + } +} + +/* Thinking process: State: at i level, f[i] is the ways to climb to i position. Function: f[i] = f[i-1] + f[i-2]. - f[i] is constructed from 2 branches: - Last step is 1 from f[i-1] - Last step is 2 from f[i-2] - This idea can be presented using a tree. However we don’t need to do recursive. We just need to use two pointers to withhold 2 level’s values. + f[i] is constructed from 2 branches: + Last step is 1 from f[i-1] + Last step is 2 from f[i-2] + This idea can be presented using a tree. However we don’t need to do recursive. We just need to use two pointers to withhold 2 level’s values. Init: The for loop starts at level2, so before level 2 there are 2 init states: - f[0] == 1. This means we jump 2 steps from level0 to level2. - f[i] == 1. This means we jump 1 steps to level1, then jump another step to level2 + f[0] == 1. This means we jump 2 steps from level0 to level2. + f[i] == 1. This means we jump 1 steps to level1, then jump another step to level2 Answer: f[n] */ - public class Solution { /** * @param n: An integer @@ -42,3 +136,5 @@ public int climbStairs(int n) { } + +``` \ No newline at end of file diff --git a/Java/Clone Graph.java b/Java/Clone Graph.java index eeaabe3..93c305e 100644 --- a/Java/Clone Graph.java +++ b/Java/Clone Graph.java @@ -1,3 +1,11 @@ +M + +Use HashMap to mark cloned nodes. + +先能复制多少Node复制多少。然后把neighbor 加上 + + +``` /* Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. @@ -23,7 +31,7 @@ \_/ Hide Tags Depth-first Search Breadth-first Search Graph - + */ /* @@ -134,3 +142,5 @@ public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { } } + +``` diff --git a/Java/Closest Binary Search Tree Value.java b/Java/Closest Binary Search Tree Value.java new file mode 100644 index 0000000..d68ba76 --- /dev/null +++ b/Java/Closest Binary Search Tree Value.java @@ -0,0 +1,56 @@ +E + +Binary Search. 记录找到过的closest. 直到tree leaf, 找完return + +``` +/* +Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. + +Note: +Given target value is a floating point. +You are guaranteed to have only one unique value in the BST that is closest to the target. + +Tags: Tree Binary Search +Similar Problems: (M) Count Complete Tree Nodes, (H) Closest Binary Search Tree Value II + +*/ + + +/* +Thoughts: +Binary search, maintain a closest value. +Note: initial closest in real case is just the root, since we start from the root +*/ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public int closestValue(TreeNode root, double target) { + if (root == null) { + return 0; + } + double closest = root.val; + while (root != null) { + if (root.val == target) { + return root.val; + } else { + if (Math.abs(target - closest) >= Math.abs(target - root.val)) { + closest = root.val; + } + if (root.val > target) { + root = root.left; + } else { + root = root.right; + } + } + }//END while + return (int)closest; + } +} +``` \ No newline at end of file diff --git a/Java/Closest Number in Sorted Array.java b/Java/Closest Number in Sorted Array.java index 29ab136..13f8231 100644 --- a/Java/Closest Number in Sorted Array.java +++ b/Java/Closest Number in Sorted Array.java @@ -1,5 +1,9 @@ -Binary search. 考虑mid-1, mid+1. -一旦没有mid = target.index。 那么target最终就narrow down在(mid-1,mid) 或者(mid,mid+1) +E + +跟Closest Binary Search Tree Vlaue类似: + +Binary search. 考虑mid-1, mid+1. +一旦没有mid = target.index。 那么target最终就narrow down在(mid-1,mid) 或者(mid,mid+1) ``` /* Given a target number and an integer array A sorted in ascending order, find the index i in A such that A[i] is closest to the given target. diff --git a/Java/ColorGrid.java b/Java/ColorGrid.java new file mode 100644 index 0000000..9fbee5c --- /dev/null +++ b/Java/ColorGrid.java @@ -0,0 +1,155 @@ +M + +用HashMap, 理解题目规律,因为重复的计算可以被覆盖,所以是个优化题。 + +消灭重合点: +如果process当下col, 其实要减去过去所有加过的row的交接点。。。 +再分析,就是每次碰到row 取一个单点, sumRow += xxx。 +然后process当下col时候, sum += colValue * N - sumRow. 就等于把交叉所有row(曾经Process过的row)的点减去了。很方便。 + +最后read in 是O(P), process也是O(P). + + +``` + +/* +HackerRank. +You are given an N×NN×N grid. Each cell has the color white (color 0) in the beginning. + +Each row and column has a certain color associated with it. Filling a row or column with a new color VV means changing all the cells of that row or column to VV (thus overriding the previous colors of the cells). + +Now, given a sequence of PP such operations, calculate the sum of the colors in the final grid. + +For simplicity, the colors will be positive integers whose values will be most 109109. + +Input Format +The first line of input contains two integers NN and PP separated by a space. +The next PP lines each contain a filling operation. There are two types of filling operations. + +ROW I V which means "fill row II with color VV". +COL I V which means "fill column II with color VV". +Output Format +Output one line containing exactly one integer which is the sum of the colors in the final grid. + +Constraints +1≤N≤60001≤N≤6000 +1≤P≤4000001≤P≤400000 +1≤I≤N1≤I≤N +1≤V≤1091≤V≤109 + +Sample Input + +5 4 +COL 1 6 +COL 4 11 +ROW 3 9 +COL 1 24 +Sample Output + +200 +Explanation +There are four operations. After the second operation, the grid looks like + + 6 0 0 11 0 + 6 0 0 11 0 + 6 0 0 11 0 + 6 0 0 11 0 + 6 0 0 11 0 +After the third operation (ROW 3 9), the third row was colored with 9, overriding any previous color in the cells. + + 6 0 0 11 0 + 6 0 0 11 0 + 9 9 9 9 9 + 6 0 0 11 0 + 6 0 0 11 0 +After the fourth operation (COL 1 24), the grid becomes: + +24 0 0 11 0 +24 0 0 11 0 +24 9 9 9 9 +24 0 0 11 0 +24 0 0 11 0 +The sum of the colors in this grid is 200. + +*/ + +import java.io.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.util.regex.*; +/* +Thoughts: +This is for practice. I didn't run much tests on the code. + Store info into class Cell {int x; boolean isRow; long value} + Save to arraylist. Later need to call list.remove(object) + Use hash map to store the appearance + process the final data: + keep track of curr single row cell sum = rowSum; also colSum + during process: add up n*colorValue. + if row, minus rowSum + if col, minus colSum +*/ +public class Solution { + class Cell { + int x; + boolean isRow; + long value; + public Cell(String s) { + String[] ss = s.split(" "); + this.isRow = ss[0].charAt(0) == 'R'; + this.x = Integer.parseInt(ss[1]); + this.value = Long.parseLong(ss[2]); + } + } + public static void main(String[] args) { + Solution sol = new Solution(); + + Scanner in = new Scanner(System.in); + String[] ss = in.nextLine().split(" "); + int N = Integer.parseInt(ss[0]); + int P = Integer.parseInt(ss[1]); + + //Storage + HashMap map = new HashMap(); + ArrayList list = new ArrayList(); + + while (P != 0) {//O(P) + //create Cell + String s = in.nextLine(); + Cell cell = sol.new Cell(s); + //add into list + list.add(cell); + //Check if cell exist in map. + //if exist in map, replace it with current cell, and remove old cell from list + String key = s.substring(0, s.lastIndexOf(" ")); + if (!map.containsKey(key)) { + map.put(key, cell); + } else { + Cell oldCell = map.get(key); + map.put(key, cell); + list.remove(oldCell); + } + P--; + } + + //Process final results + int sumCol = 0; + int sumRow = 0; + long sum = 0; + for (int i = 0; i < list.size(); i++) {//O(P) + Cell cell = list.get(i); + sum += cell.value * N; + if (cell.isRow) { + sum -= sumCol; + sumRow += cell.value; + } else { + sum -= sumRow; + sumCol += cell.value; + } + } + + System.out.println(sum); + } +} +``` \ No newline at end of file diff --git a/Java/Combination Sum II.java b/Java/Combination Sum II.java index 001b450..4aa8dfd 100644 --- a/Java/Combination Sum II.java +++ b/Java/Combination Sum II.java @@ -1,4 +1,7 @@ -确保Helper是用i+1,下一层的数字。 +M + +还是DFS. 和Combination Sum I 类似. +确保Helper是用i+1,下一层的数字, 不允许重复。 ``` /* diff --git a/Java/Combination Sum.java b/Java/Combination Sum.java index 0566a71..a83f79f 100644 --- a/Java/Combination Sum.java +++ b/Java/Combination Sum.java @@ -1,5 +1,19 @@ -递归,backtracking. 非常normal。 -记得求sum时候也pass 一个sum进去,backtracking一下sum也,这样就不必每次都sum the list了。 +M + +递归,backtracking. 非常normal。需要先sort. +记得求sum时候也pass 一个sum进去,backtracking一下sum也,这样就不必每次都sum the list了。 + +题目里面所同一个元素可以用n次,但是,同一种solution不能重复出现。如何handle? + +1. 用一个index (我们这里用了start)来mark每次recursive的起始点。 +2. 每个recursive都从for loop里面的i开始,而i = start。 也就是,下一个iteration,这个数字会有机会被重复使用。 +3. 同时,确定在同一个for loop里面,不同的Index上面相同的数字,不Process两遍。用一个prev 作为checker. + +假如[x1, x2, y, z], where x1 == x2, 上面做法的效果: +我们可能有这样的结果: x1,x1,x1,y,z +但是不会有:x1,x2,x2,y,z +两个solution从数字上是一样的,也就是duplicated solution, 要杜绝第二种。 + ``` /* Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. diff --git a/Java/Combinations.java b/Java/Combinations.java index 2286e9b..ea6893d 100644 --- a/Java/Combinations.java +++ b/Java/Combinations.java @@ -1,3 +1,10 @@ +M + +Combination DFS。 画个图想想. 每次从1~n里面pick一个数字i + +因为下一层不能重新回去 [0~i]选,所以下一层recursive要从i+1开始选。 + +``` /* Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. @@ -14,11 +21,6 @@ */ public class Solution { - /** - * @param n: Given the range of numbers - * @param k: Given the numbers of combinations - * @return: All the combinations of k numbers out of 1..n - */ public List> combine(int n, int k) { List> rst = new ArrayList>(); if (n <= 0 || k <= 0) { @@ -42,3 +44,5 @@ public void helper(List> rst, } } + +``` \ No newline at end of file diff --git a/Java/Compare Strings.java b/Java/Compare Strings.java index 1cf9b3a..8d83fc4 100644 --- a/Java/Compare Strings.java +++ b/Java/Compare Strings.java @@ -1,3 +1,10 @@ +E + +比较一下大小, null. + +然后用char[]来count chars from A. 再对照chars in B. + +``` /* Compare two strings A and B, determine whether A contains all of the characters in B. @@ -42,3 +49,5 @@ public boolean compareStrings(String A, String B) { } } + +``` \ No newline at end of file diff --git a/Java/Complete Binary Tree.java b/Java/Complete Binary Tree.java index 03fbba4..93c7027 100644 --- a/Java/Complete Binary Tree.java +++ b/Java/Complete Binary Tree.java @@ -1,8 +1,12 @@ -Use a flag . 当出现了第一次有 null children的node的时候, -说明complete tree的最低level出现了。 -自此以后,再不该有node再有child, queue后面出现的node应该左右孩子都是null. +E + +BFS + +Use a flag . 当出现了第一次有 null children的node的时候, +说明complete tree的最低level出现了。 +自此以后,queue再不该有node再有child, queue后面出现的node的左右孩子应该都是null. + -用BFS ``` /* Check a binary tree is completed or not. A complete binary tree is not binary tree that every level is completed filled except the deepest level. In the deepest level, all nodes must be as left as possible. See more definition diff --git a/Java/Construct Binary Tree from Inorder and Postorder Traversal.java b/Java/Construct Binary Tree from Inorder and Postorder Traversal.java old mode 100644 new mode 100755 index fcdb29a..d23e140 --- a/Java/Construct Binary Tree from Inorder and Postorder Traversal.java +++ b/Java/Construct Binary Tree from Inorder and Postorder Traversal.java @@ -1,3 +1,15 @@ +M + +写个Inorder和Postorder的例子。利用他们分left/right subtree的规律解题。 + +Postorder array 的末尾, 就是当下层的root. +在Inorder array 里面找到这个root,就刚好把左右两边分割成left/right tree。 + +这题比较tricky地用了一个helper做recursive。 特别要注意处理index的变化, precisely考虑开头结尾 + +可惜有个不可避免的O(n) find element in array. + +``` /* Given inorder and postorder traversal of a tree, construct the binary tree. @@ -19,18 +31,18 @@ Thinking process: Know that the last element of PostOrder array is the root of the Binary tree. -Find this root from the InOrder array, which will be the middle point. The front-part of the inorder array will be left-tree, the end-part of the inorder array will be the right-tree. +Find this root from the InOrder array. The front-part of the inorder array will be left-tree, the end-part of the inorder array will be the right-tree. Trick part: 1. Need a helper function to perfrom divide/conquer. 2. Need to be careful when cutting the inorder and postorder array. - For inorder array, left array: (instart, middlePosition -1), right array: (middlePosition + 1, inend) - For postorder array: when cutting, we know the very last node is cut off already, so we just need to evenly split the rest array. - left array(postStart, postStart + (middlePosition - instart) - 1). - Note: (middlePositon - instart) means the length of the left-array/size of the left-tree - However, postStart + left-array-length exceed 1 over postorder-left-tree, hence minus 1 here. - right array(postStart + (middlePosition - instart), postend - 1) - Note: postStart + left-tree-length is exactly the starting point of the post-right-array. - Because the ending element is cut off previously to serve as root, we need to do (postend - 1) for correct postorder-right-tree. + For inorder array, left array: (instart, middlePosition -1), right array: (middlePosition + 1, inend) + For postorder array: when cutting, we know the very last node is cut off already, so we just need to evenly split the rest array. + left array(postStart, postStart + (middlePosition - instart) - 1). + Note: (middlePositon - instart) means the length of the left-array/size of the left-tree + However, postStart + left-array-length exceed 1 over postorder-left-tree, hence minus 1 here. + right array(postStart + (middlePosition - instart), postend - 1) + Note: postStart + left-tree-length is exactly the starting point of the post-right-array. + Because the ending element is cut off previously to serve as root, we need to do (postend - 1) for correct postorder-right-tree. */ @@ -48,11 +60,7 @@ Because the ending element is cut off previously to serve as root, we need to do public class Solution { - /** - *@param inorder : A list of integers that inorder traversal of a tree - *@param postorder : A list of integers that postorder traversal of a tree - *@return : Root of a tree - */ + public TreeNode buildTree(int[] inorder, int[] postorder) { if (inorder.length != postorder.length) { return null; @@ -85,3 +93,5 @@ public int findMid(int[] arr, int start, int end, int key) { } } + +``` \ No newline at end of file diff --git a/Java/Construct Binary Tree from Inorder and Preorder Traversal.java b/Java/Construct Binary Tree from Inorder and Preorder Traversal.java old mode 100644 new mode 100755 index 3026d0d..fb69f8b --- a/Java/Construct Binary Tree from Inorder and Preorder Traversal.java +++ b/Java/Construct Binary Tree from Inorder and Preorder Traversal.java @@ -1,3 +1,10 @@ +M + +和Construct from Inorder && Postorder 想法一样。 + +写出Preorder和Inorder的字母例子,发现Preorder的开头总是这Level的root。依此写helper,注意处理index。 + +``` /* Given preorder and inorder traversal of a tree, construct the binary tree. @@ -39,11 +46,6 @@ public class Solution { - /** - *@param preorder : A list of integers that preorder traversal of a tree - *@param inorder : A list of integers that inorder traversal of a tree - *@return : Root of a tree - */ public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder.length != inorder.length) { return null; @@ -77,3 +79,5 @@ public int findMid(int[] arr, int start, int end, int key) { } } + +``` \ No newline at end of file diff --git a/Java/Convert Binary Search Tree to Doubly Linked List.java b/Java/Convert Binary Search Tree to Doubly Linked List.java index 2efc30d..c977d71 100644 --- a/Java/Convert Binary Search Tree to Doubly Linked List.java +++ b/Java/Convert Binary Search Tree to Doubly Linked List.java @@ -1,15 +1,19 @@ -注意inorder traversal在check right node的事后, -不论right == null or != null, 每次都要强行move to right. +M + +会iterative traverse Binary Search Tree就好(Stack && handle left-dig-down), 然后create Doubly-ListNode 时候注意就好. + +注意inorder traversal在check right node的事后, +不论right == null or != null, 每次都要强行move to right. + +如果不node = node.right, +很可能发生窘境: +node alays = stack.top(), 然后stack.top()一直是一开始把left 全部遍历的内容。所以就会infinite loop, 永远在左边上下上下。 -如果不node = node.right, -很可能发生窘境: -node alays = stack.top(), 然后stack.top()一直是一开始把left 全部遍历的内容。所以就会infinite loop, 永远在左边上下上下。 ``` /* Convert a binary search tree to doubly linked list with in-order traversal. -Have you met this question in a real interview? Yes Example Given a binary search tree: @@ -58,10 +62,6 @@ boarder case: if null, return a null. */ public class Solution { - /** - * @param root: The root of tree - * @return: the head of doubly list node - */ public DoublyListNode bstToDoublyList(TreeNode root) { if (root == null) { return null; diff --git a/Java/Convert Expression to Polish Notation.java b/Java/Convert Expression to Polish Notation.java old mode 100644 new mode 100755 index 7046567..6c33ca3 --- a/Java/Convert Expression to Polish Notation.java +++ b/Java/Convert Expression to Polish Notation.java @@ -1,5 +1,11 @@ +H + 还是Expression Tree (Min-Tree). + 根据题意,Tree出来以后,来个Pre-order-traversal. + +Note: label需要是String.虽然 Operator是长度为1的char, 但是数字可为多位。 + ``` /* Given an expression string array, return the Polish notation of this expression. (remove the parentheses) @@ -25,93 +31,94 @@ */ public class Solution { - class TreeNode { - String s; - int val; - TreeNode left; - TreeNode right; - public TreeNode(int val, String s) { - this.val = val; - this.s = s; - this.left = null; - this.right = null; - } - } - - public TreeNode build(String[] expression) { - if (expression == null || expression.length == 0) { - return null; - } - Stack stack = new Stack(); - int base = 0; - int val = 0; - - for (int i = 0; i < expression.length; i++) { - if (expression[i].equals("(")) { - base += 10; - continue; - } - if (expression[i].equals(")")) { - base -= 10; - continue; - } - val = getWeight(base, expression[i]); - TreeNode node = new TreeNode(val, expression[i]); - while (!stack.isEmpty() && node.val <= stack.peek().val) { - node.left = stack.pop(); - } - if (!stack.isEmpty()) { - stack.peek().right = node; - } - stack.push(node); - } - if (stack.isEmpty()) { - return null; - } - TreeNode rst = stack.pop(); - while (!stack.isEmpty()) { - rst = stack.pop(); - } - return rst; - } - - public int getWeight(int base, String s) { - if (s.equals("+") || s.equals("-")) { - return base + 1; - } - if (s.equals("*") || s.equals("/")) { - return base + 2; - } - return Integer.MAX_VALUE; - } + class TreeNode { + String s; + int val; + TreeNode left; + TreeNode right; + public TreeNode(int val, String s) { + this.val = val; + this.s = s; + this.left = null; + this.right = null; + } + } + + public TreeNode build(String[] expression) { + if (expression == null || expression.length == 0) { + return null; + } + Stack stack = new Stack(); + int base = 0; + int val = 0; + + for (int i = 0; i < expression.length; i++) { + if (expression[i].equals("(")) { + base += 10; + continue; + } + if (expression[i].equals(")")) { + base -= 10; + continue; + } + val = getWeight(base, expression[i]); + TreeNode node = new TreeNode(val, expression[i]); + while (!stack.isEmpty() && node.val <= stack.peek().val) { + node.left = stack.pop(); + } + if (!stack.isEmpty()) { + stack.peek().right = node; + } + stack.push(node); + } + if (stack.isEmpty()) { + return null; + } + TreeNode rst = stack.pop(); + while (!stack.isEmpty()) { + rst = stack.pop(); + } + return rst; + } + + public int getWeight(int base, String s) { + if (s.equals("+") || s.equals("-")) { + return base + 1; + } + if (s.equals("*") || s.equals("/")) { + return base + 2; + } + return Integer.MAX_VALUE; + } /** * @param expression: A string array * @return: The Polish notation of this expression */ public ArrayList convertToPN(String[] expression) { - ArrayList rst = new ArrayList(); - if (expression == null || expression.length == 0) { - return rst; - } - TreeNode root = build(expression); - preTraversal(rst, root); - - return rst; + ArrayList rst = new ArrayList(); + if (expression == null || expression.length == 0) { + return rst; + } + TreeNode root = build(expression); + preTraversal(rst, root); + + return rst; } public void preTraversal(ArrayList rst, TreeNode node){ - if (node == null) { - return; - } - if (node.left == null && node.right == null) { - rst.add(node.s); - return; - } - rst.add(node.s); - preTraversal(rst, node.left); - preTraversal(rst, node.right); + if (node == null) { + return; + } + if (node.left == null && node.right == null) { + rst.add(node.s); + return; + } + rst.add(node.s); + preTraversal(rst, node.left); + preTraversal(rst, node.right); } } + ``` \ No newline at end of file diff --git a/Java/Convert Expression to Reverse Polish Notation.java b/Java/Convert Expression to Reverse Polish Notation.java old mode 100644 new mode 100755 index 6b0df9f..26e9c73 --- a/Java/Convert Expression to Reverse Polish Notation.java +++ b/Java/Convert Expression to Reverse Polish Notation.java @@ -1,6 +1,11 @@ -用build expression tree开头。 +H + +build expression tree。 + 这个里面把TreeNode就当做成我们需要的node,里面扩展成有left/right child的node. -这题,目的是建造tree,然后来个post-traversal就行了。 + +建造Expression Tree,然后根据 Reverse Polish Notation 的定义,来个post-traversal就行了。 + ``` /* Given an expression string array, return the Reverse Polish notation of this expression. (remove the parentheses) diff --git a/Java/Convert Integer A to Integer B.java b/Java/Convert Integer A to Integer B.java index 97b3974..35ce992 100644 --- a/Java/Convert Integer A to Integer B.java +++ b/Java/Convert Integer A to Integer B.java @@ -1,3 +1,14 @@ +E + +Bit Manipulation + +a^b 显示出bit format里面有不同binary code的数位. + +每次 (a^b)>>i 移动i位之后, 再 & 1时其实是指留下这一位的数字. + +count it up + +``` /* Determine the number of bits required to convert integer A to integer B @@ -32,3 +43,5 @@ public static int bitSwapRequired(int a, int b) { }; + +``` \ No newline at end of file diff --git a/Java/Convert Sorted Array to Binary Search Tree With Minimal Height.java b/Java/Convert Sorted Array to Binary Search Tree With Minimal Height.java index dccdbe6..4d54131 100644 --- a/Java/Convert Sorted Array to Binary Search Tree With Minimal Height.java +++ b/Java/Convert Sorted Array to Binary Search Tree With Minimal Height.java @@ -1,3 +1,8 @@ +E + +Binary Search的感觉. 中间一开两半, divde and conquer,左右各自recursive下去build left/right child. + +``` /* Given a sorted (increasing order) array, Convert it to create a binary tree with minimal height. @@ -19,8 +24,8 @@ Given a sorted (increasing order) array, Convert it to create a binary tree with Thoughts: 1. Find middle point x. 2. All index before x, goes to left of the tree. Same apply to right tree - build sub array and pass alone: we can pass index start, end. - use parent node and pass along + build sub array and pass alone: we can pass index start, end. + use parent node and pass along 3. Recur on left side array. */ @@ -45,22 +50,24 @@ public class Solution { public TreeNode sortedArrayToBST(int[] A) { TreeNode root = null; if (A == null || A.length == 0) { - return root; + return root; } root = helper(0, A.length - 1, A); return root; } public TreeNode helper(int start, int end, int[] A) { - if (start > end) { - return null; - } - //add middle node - int mid = start + (end - start)/2; - TreeNode node = new TreeNode(A[mid]); - //Split and append child - node.left = helper(start, mid - 1, A); - node.right = helper(mid + 1, end, A); - return node; + if (start > end) { + return null; + } + //add middle node + int mid = start + (end - start)/2; + TreeNode node = new TreeNode(A[mid]); + //Split and append child + node.left = helper(start, mid - 1, A); + node.right = helper(mid + 1, end, A); + return node; } } + +``` \ No newline at end of file diff --git a/Java/Convert Sorted List to Binary Search Tree.java b/Java/Convert Sorted List to Binary Search Tree.java index 3295e98..a7ca482 100644 --- a/Java/Convert Sorted List to Binary Search Tree.java +++ b/Java/Convert Sorted List to Binary Search Tree.java @@ -1,14 +1,17 @@ -Divide and Conquer +M -找到mid。 -然后把root = mid.next +Divide and Conquer +用快慢pointer -然后开始sortedListToBST(mid.next.next); //后半段 -mid.next = null;//非常重要,要把后面拍过序的断掉 -sortedListToBST(head); //从头开始的前半段 +找到mid。 +然后把root = mid.next +然后开始sortedListToBST(mid.next.next); //后半段 +mid.next = null;//非常重要,要把后面拍过序的断掉 +sortedListToBST(head); //从头开始的前半段 -最后root.left, root.right merge一下。 + +最后root.left, root.right merge一下。 ``` /* diff --git a/Java/Copy List with Random Pointer.java b/Java/Copy List with Random Pointer.java old mode 100644 new mode 100755 index 481895f..8b9facb --- a/Java/Copy List with Random Pointer.java +++ b/Java/Copy List with Random Pointer.java @@ -1,15 +1,25 @@ +M + +Basic Implementation, 其中用了一下HashMap: + +遍历head.next .... null. +每一步都check map里面有没有head。没有?加上。 +每一步都check map里面有没有head.random。没有?加上。 + +``` /* -31% Accepted + A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null. Return a deep copy of the list. -Example -Tags Expand -Hash Table Linked List +Hide Company Tags Microsoft Uber +Hide Tags Hash Table Linked List +Hide Similar Problems (M) Clone Graph -*/ +LeetCode: Hard +*/ /** * Definition for singly-linked list with a random pointer. @@ -31,16 +41,14 @@ border case: if head == null, return null */ - public class Solution { public RandomListNode copyRandomList(RandomListNode head) { if (head == null) { return null; } //creat node, used to link all nodes - RandomListNode dummy = new RandomListNode(0); - RandomListNode node = dummy; - RandomListNode newNode; + RandomListNode node = new RandomListNode(0); + RandomListNode dummy = node; //HashMap to mark node HashMap map = new HashMap(); @@ -50,15 +58,13 @@ public RandomListNode copyRandomList(RandomListNode head) { if (!map.containsKey(head)) { map.put(head, new RandomListNode(head.label)); } - newNode = map.get(head); - node.next = newNode; + node.next = map.get(head); //process head.random if (head.random != null) { if(!map.containsKey(head.random)) { map.put(head.random, new RandomListNode(head.random.label)); } - newNode = map.get(head.random); - node.next.random = newNode; + node.next.random = map.get(head.random); } node = node.next; head = head.next; @@ -67,6 +73,7 @@ public RandomListNode copyRandomList(RandomListNode head) { } } + /* Thinking process: 1. Loop through the original list @@ -80,10 +87,6 @@ public RandomListNode copyRandomList(RandomListNode head) { */ public class Solution { - /** - * @param head: The head of linked list with a random pointer. - * @return: A new head of a deep copy of the list. - */ public RandomListNode copyRandomList(RandomListNode head) { if (head == null) { return null; @@ -118,3 +121,44 @@ public RandomListNode copyRandomList(RandomListNode head) { } } +//Same soluton as above, but split populating map && deep copy, which is not as efficient as above +//Save all possible nodes into HashMap + //Deep copy the list, before adding any node, check map +public class Solution { + public RandomListNode copyRandomList(RandomListNode head) { + if (head == null) { + return null; + } + //Populate map + HashMap map = new HashMap(); + RandomListNode node = head; + RandomListNode newNode; + while(node != null) { + if (!map.containsKey(node)) { + newNode = new RandomListNode(node.label); + map.put(node, newNode); + } + if (node.random != null && !map.containsKey(node.random)) { + newNode = new RandomListNode(node.random.label); + map.put(node.random, newNode); + } + node = node.next; + } + //Deep copy + node = head; + newNode = new RandomListNode(0); + RandomListNode dummy = newNode; + while (node != null) { + newNode.next = map.get(node); + if (node.random != null) + newNode.next.random = map.get(node.random); + newNode = newNode.next; + + node = node.next; + } + + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Java/Cosine Similarity.java b/Java/Cosine Similarity.java index c71919e..afa16bb 100644 --- a/Java/Cosine Similarity.java +++ b/Java/Cosine Similarity.java @@ -1,7 +1,11 @@ -按题目意思,写出来就好了。 +E + +basic implementation + ``` /* -Cosine similarity is a measure of similarity between two vectors of an inner product space that measures the cosine of the angle between them. +Cosine similarity is a measure of similarity between two vectors of an inner product space + that measures the cosine of the angle between them. The cosine of 0° is 1, and it is less than 1 for any other angle. See wiki: Cosine Similarity diff --git a/Java/Count 1 in Binary.java b/Java/Count 1 in Binary.java index 1059210..f44a5c3 100644 --- a/Java/Count 1 in Binary.java +++ b/Java/Count 1 in Binary.java @@ -1,3 +1,10 @@ +E + +1. 可以把integer -> string -> char array. + +2. 或者就 count += num << i & 1 + +``` /* Count how many 1 in binary representation of a 32-bit integer. @@ -41,3 +48,5 @@ public int countOnes(int num) { return sum; } }; + +``` \ No newline at end of file diff --git a/Java/Count Primes.java b/Java/Count Primes.java new file mode 100644 index 0000000..2888f30 --- /dev/null +++ b/Java/Count Primes.java @@ -0,0 +1,88 @@ +E + +什么是prime number: >=2的没有除自己和1以外公约数的数。 + +还有另外一个定义方法!! +这个n,有没有小于n的一个i,而达到: i*i + # of i = n. 如果有,那就不是 prime。 + +方法很牛逼也很数学。没做的时候可能想不到。做了之后就觉得,哎,我去,有道理啊。 +简而言之:简历一个boolean长条,存isPrime[]。 然后从i=2, 全部变true. +然后利用这个因子的性质,非prime满足条件: self*self, self * self + self ... etc. +所以就check每一个j, j+i, j+i+i, 然后把所有non-prime全部mark成false. +最后,数一遍还剩下的true个数就好了 + +``` +/* +Description: +Count the number of prime numbers less than a non-negative number, n. +Tags: Hash Table, Math +Similar Problems: (E) Ugly Number, (M) Ugly Number II, (M) Perfect Squares +*/ + +/* +Attempt2: https://leetcode.com/problems/count-primes/ explains it well +1. Ignore 1 and n. Don't count 1 and the number itself in. +2. Assume all numbers are prime in a boolean[]. Check off those are certainly not prime, the remaining will be prime. +3. For any n, only need to check up to i * i < n; more than that, +for example 2 x 6 is same as checking 6x2, but 6x2 is not necessary to check. +4. How to mark things off: + The first non-prime is always i^2: self * self. + Then more non-primes:self * self, self * (self + 1), self * (self + 2) ... etc. + So, mark all of these index of in the boolean[] + +*/ +public class Solution { + public int countPrimes(int n) { + if (n <= 1) { + return 0; + } + boolean[] primes = new boolean[n]; + for (int i = 2; i < primes.length; i++) { + primes[i] = true; + } + + for (int i = 2; i * i< n; i++) { + if (!primes[i]) { + continue; + } + for (int j = i * i; j < n; j += i) { + primes[j] = false; + } + } + int count = 0; + for (int i = 2; i < primes.length; i++) { + count += primes[i] ? 1 : 0; + } + return count; + } +} + + +/*Timeout version*/ +//prime is a number n that cannot be divided by any number < n. +//In fact, only need to check sqrt(n) numbers from 1 + +public class Solution { + public int countPrimes(int n) { + int count = 0; + for (int i = 1; i < n; i++) { + if (isPrime(i)) { + count++; + } + } + return count; + } + + public boolean isPrime(int num) { + if (num <= 1) return false; + for (int i = 2; i * i <= num; i++) { + if (num % i == 0) { + return false; + } + } + return true; + } +} + + +``` \ No newline at end of file diff --git a/Java/Count and Say.java b/Java/Count and Say.java index 2d0fc5b..76637a7 100644 --- a/Java/Count and Say.java +++ b/Java/Count and Say.java @@ -1,3 +1,8 @@ +E + +Basic implementation. Count duplicates and print + +``` /* The count-and-say sequence is the sequence of integers beginning as follows: @@ -40,23 +45,25 @@ public String countAndSay(int n) { String str = "11"; int ind = 2; while (ind < n) { - StringBuffer sb = new StringBuffer(); - char[] arr = str.toCharArray(); - int count = 1; - int type = Character.getNumericValue(arr[0]); - for (int i = 1; i < arr.length; i++) { - if (arr[i] == arr[i - 1]) { - count++; - } else { - sb.append(count + "" + type); - type = Character.getNumericValue(arr[i]); - count = 1; - } - } - ind++; - sb.append(count + "" + type); - str = sb.toString(); + StringBuffer sb = new StringBuffer(); + char[] arr = str.toCharArray(); + int count = 1; + int type = Character.getNumericValue(arr[0]); + for (int i = 1; i < arr.length; i++) { + if (arr[i] == arr[i - 1]) { + count++; + } else { + sb.append(count + "" + type); + type = Character.getNumericValue(arr[i]); + count = 1; + } + } + ind++; + sb.append(count + "" + type); + str = sb.toString(); } return str; } } + +``` \ No newline at end of file diff --git a/Java/Count of Smaller Number before itself.java b/Java/Count of Smaller Number before itself.java old mode 100644 new mode 100755 index 1d0b9a8..87df7ee --- a/Java/Count of Smaller Number before itself.java +++ b/Java/Count of Smaller Number before itself.java @@ -1,21 +1,28 @@ -与Count of Smaller Number非常类似。 -Trick: 先Query,再modify. -每次Query时候,A[i]都还没有加入到Segment Tree 里面,而A[i+1...etc]自然也还没有加进去。 -那么就自然是coutning smaller number before itself. -刁钻啊! +H + +与Count of Smaller Number非常类似。以实际的value来构成segment tree,leaf上存(count of smaller number)。 + +Trick: 先Query,再modify. +每次Query时候,A[i]都还没有加入到Segment Tree 里面,而A[i+1,...etc]自然也还没有加进去。 +那么就自然是coutning smaller number before itself. +刁钻啊! + +另外注意: +在modify里面:多Check了root.start <= index 和 index <= root.end。 过去都忽略了。以后可以把这个也写上。 +(其实是Make sense的,就是更加严格地check了index再 root.left 或者 root.right里面的站位) -另外注意: -在modify里面:多Check了root.start <= index 和 index <= root.end。 过去都忽略了。以后可以把这个也写上。 -(其实是Make sense的,就是更加严格地check了index再 root.left 或者 root.right里面的站位) ``` /* -Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) . For each element Ai in the array, count the number of element before this element Ai is smaller than it and return count number array. +Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) . +For each element Ai in the array, count the number of element before this element Ai is smaller than +it and return count number array. Example For array [1,2,7,8,5], return [0,1,2,3,2] Note -We suggest you finish problem Segment Tree Build, Segment Tree Query II and Count of Smaller Number before itself I first. +We suggest you finish problem Segment Tree Build, Segment Tree Query II and +Count of Smaller Number before itself I first. Tags Expand LintCode Copyright Binary Tree Segment Tree diff --git a/Java/Count of Smaller Number.java b/Java/Count of Smaller Number.java old mode 100644 new mode 100755 index c8b4083..69e7096 --- a/Java/Count of Smaller Number.java +++ b/Java/Count of Smaller Number.java @@ -1,15 +1,33 @@ -和平时的segment tree问题不同。 -这个给了实际的value,而还是造一个based on index的segment tree才行。 -Thought1是失败的,因为虽然省了空间,但是search time还是O(n). -Thought2才是真正的segment tree (based on index interval). +M + +和平时的segment tree问题不同。 0 ~ n-1代表实际数字。是造一个based on real value的segment tree. +Modify时,把array里面的value带进去,找到特定的位子(leaf),然后count+1. + +最终在SegmentTree leaf上面全是array里面实际的数字。 + +trick: +在query前,给进去的start和end是: 0 ~ value-1. +value-1就是说,找比自己所在range小1的range(那么自然而然地就不包括自己了),这样就找到了smaller number. + + +[那么其他做过的SegmentTree是怎么样呢?] +那些构成好的SegmentTree(找min,max,sum)也有一个Array。但是构成Tree时候,随Array的index而构架。 +也就是说,假如有Array[x,y,....]:在leaf,会有[0,0] with value = x. [1,1] with value = y. + +[但是这题] +构成时,是用actual value.也就是比如Array[x,y,....]会产生leaf:[x,x]with value = ..; [y,y]with value =... + +其实很容易看穿: +若给出一个固定的array构成 SegmentTree,那估计很简单:按照index从0~array.lengh,leaf上就是[0,0] with value = x. + +若题目让构造一个空心SegmentTree, based on value 0 ~ n-1 (n <= 10000), 然后把一个Array的value modify 进去。 +这样八成是另外一种咯。 -重要trick: -在query前,给进去的start和end是: 0 ~ value-1. -value-1就是说,找比自己所在range小1的range(那么自然而然地就不包括自己了),这样就找到了smaller number. -这个trick还挺刁钻的。 ``` /* -Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) and an query list. For each query, give you an integer, return the number of element in the array that are smaller than the given integer. +Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) +and an query list. For each query, give you an integer, return the number of element in the array that +are smaller than the given integer. Example @@ -27,6 +45,11 @@ Give you an integer array (index from 0 to n-1, where n is the size of this arra Tags Expand Binary Search LintCode Copyright Segment Tree +*/ + +/* +Thought1是失败的,因为虽然省了空间,但是search time还是O(n). +Thought2才是真正的segment tree (based on index interval). */ /* Thought2: http://www.jiuzhang.com/solutions/count-of-smaller-number/ @@ -34,9 +57,10 @@ Give you an integer array (index from 0 to n-1, where n is the size of this arra Use query method to search for final results. Each A[i] will be stored at index value of A[i]. Count: how many numbers do we have from bottom till this level, including the A[i] itself. - For example, at the lowest A[i] spot, SegmentTreeNode(i,i), the count == 1. + For example, at the lowest A[i] spot, SegmentTreeNode(i,i), the count == 1. - Note:Again, be careful on calculating the mid. It's usually based on root.start and root.end, instead of the target start,end interval. + Note:Again, be careful on calculating the mid. It's usually based on root.start and root.end, + instead of the target start,end interval. */ public class Solution { @@ -118,7 +142,7 @@ public ArrayList countOfSmallerNumber(int[] A, int[] queries) { } for (int value : queries) { int count = 0; - if (value > 0) { + if (value > 0) {//Given value has to be in n's range: [0, 10000] count = query(root, 0, value - 1); } rst.add(count); diff --git a/Java/Course Schedule II.java b/Java/Course Schedule II.java new file mode 100755 index 0000000..306543a --- /dev/null +++ b/Java/Course Schedule II.java @@ -0,0 +1,107 @@ +M + +详细的中文分析,看Course Schedule I + +``` +/* +There are a total of n courses you have to take, labeled from 0 to n - 1. + +Some courses may have prerequisites, for example to take course 0 you have to first take course 1, +which is expressed as a pair: [0,1] + +Given the total number of courses and a list of prerequisite pairs, +return the ordering of courses you should take to finish all courses. + +There may be multiple correct orders, you just need to return one of them. +If it is impossible to finish all courses, return an empty array. + +For example: + +2, [[1,0]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1] + +4, [[1,0],[2,0],[3,1],[3,2]] +There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. +Both courses 1 and 2 should be taken after you finished course 0. +So one correct course order is [0,1,2,3]. Another correct ordering is[0,2,1,3]. + +Note: +The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. + +click to show more hints. + +Hints: +This problem is equivalent to finding the topological order in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses. +Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort. +Topological sort could also be done via BFS. +Hide Company Tags Facebook Zenefits +Hide Tags Depth-first Search Breadth-first Search Graph Topological Sort +Hide Similar Problems (M) Course Schedule (H) Alien Dictionary (M) Minimum Height Trees + +*/ + +/* + http://blog.csdn.net/ljiabin/article/details/45847019 + + Based on Course Schedule I, now we need to return all nodes with by the seq number. + + Note: + The map is built based on +*/ +public class Solution { + HashMap> map; + int[] visited; + int seq; + int[] order; + public int[] findOrder(int numCourses, int[][] prerequisites) { + order = new int[numCourses]; + seq = numCourses - 1; + visited = new int[numCourses]; + map = new HashMap>(); + //Put all start node into map. + for (int i = 0; i < prerequisites.length; i++) { + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new ArrayList()); + } + map.get(prerequisites[i][1]).add(prerequisites[i][0]); + } + //dfs on each start node in the pair + for (int i = 0; i < numCourses; i++) { + if (!dfs(i)) { + return new int[]{}; + } + } + return order; + } + + public boolean dfs (int node) { + if (visited[node] == 1) {//has been through this path, true. + return true; + } + if (visited[node] == -1) {//visiting a visited node from a deper level node, cycle + return false; + } + //mark it -1 then after dfs mark it 1. Marking and backtracking skills + visited[node] = -1; + + //Visit each child and make sure there is no cycle. + if (map.containsKey(node)) { + for (int nextNode : map.get(node)) { + if (!dfs(nextNode)) { + return false; + } + } + } + visited[node] = 1; + order[seq--] = node; + return true; + } + +} + + + + + + +``` \ No newline at end of file diff --git a/Java/Course Schedule.java b/Java/Course Schedule.java new file mode 100755 index 0000000..ac756f7 --- /dev/null +++ b/Java/Course Schedule.java @@ -0,0 +1,228 @@ +M + +有点绕,但是做过一次就明白一点。 +是topological sort的题目。一般都是给有dependency的东西排序。 + +最终都会到一个sink node, 再不会有向后的dependency, 在那个点截止。 +我就已这样子的点为map的key, 然后value是以这个node为prerequisite的 list of courses. + +画个图的话,prerequisite都是指向那个sink node, 然后我们在组成map的时候,都是从sink node 发散回来到dependent nodes. + +在DFS里面,我们是反向的, 然后,最先完全visited的那个node, 肯定是最左边的node了,它被mark的seq也是最高的。 + +而我们的sink node,当它所有的支线都visit完了,seq肯定都已经减到最小了,也就是0,它就是第一个被visit的。 + + +最终结果: +每个有pre-requisit的node都trace上去(自底向上),并且都没有发现cycle.也就说明schedule可以用了。 + +``` +/* +There are a total of n courses you have to take, labeled from 0 to n - 1. + +Some courses may have prerequisites, for example to take course 0 you have to first take course 1, +which is expressed as a pair: [0,1] + +Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? + +For example: + +2, [[1,0]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible. + +2, [[1,0],[0,1]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0, +and to take course 0 you should also have finished course 1. +So it is impossible. + +Note: +The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. + +click to show more hints. + +Hints: +1. This problem is equivalent to finding if a cycle exists in a directed graph. + If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses. +2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort. +3. Topological sort could also be done via BFS. + +Hide Company Tags Zenefits +Hide Tags Depth-first Search Breadth-first Search Graph Topological Sort +Hide Similar Problems (M) Course Schedule II (M) Graph Valid Tree (M) Minimum Height Trees + +*/ + +/* + Thoughts: Try some help. make shorter version. + This version does not use a class, but does the exact same algorithm: mark visited and check cycle with dfs. + The idea is almost exaclty same (http://www.jyuan92.com/blog/leetcode-course-schedule/) + Instead of using a seq,visited to check mark seq, and visted, we can do a 'mark' backtracking. + This means: we can mark the visited = -1 before the dfs, and if anything in the dfs sees a -1, + it returns false; + After the dfs of children nodes in the map, wwe mark a node.visited = 1. That means the spot has been visited : ) + + Note: + SHould build he map: map +*/ + +public class Solution { + HashMap> map; + int[] visited; + public boolean canFinish(int numCourses, int[][] prerequisites) { + if (numCourses <= 0 || prerequisites == null || prerequisites.length == 0 || + prerequisites[0] == null || prerequisites[0].length == 0) { + return true; + } + visited = new int[numCourses]; + map = new HashMap>(); + //Put all start node into map. + for (int i = 0; i < prerequisites.length; i++) { + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new ArrayList()); + } + map.get(prerequisites[i][1]).add(prerequisites[i][0]); + } + //dfs on each start node in the pair + for (int i = 0; i < prerequisites.length; i++) { + if (!dfs(prerequisites[i][0])) { + return false; + } + } + + return true; + } + + public boolean dfs (int node) { + if (visited[node] == 1) {//has been through this path, true. + return true; + } + if (visited[node] == -1) {//visiting a visited node from a deper level node, cycle + return false; + } + //mark it -1 then after dfs mark it 1. Marking and backtracking skills + visited[node] = -1; + + //Visit each child and make sure there is no cycle. + if (map.containsKey(node)) { + for (int nextNode : map.get(node)) { + if (!dfs(nextNode)) { + return false; + } + } + } + + visited[node] = 1; + return true; + } + +} + + + + + + +/* + Thoughts: TO LONG. Should try shorter version. + ALSO, built the map based map: this will cause trouble and hard to work if we want to return + the sequence of course. + + Though, no need to find the correct order of course, but we can do Topological Sort via DFS, + where in the process we check if there is cycle. + 0. Create node {val, visited, list of child node}. OR: just a map + 1. Put all prerequisites in map + 2. For loop on all nodes in the map. + Each node, DFS on it, add all outgoing child on stack if that node is not visited + Check on cycle: after DFS on all child, we need to mark the parent node itself to be visited. + At this moment, if this node has been visited once, that means a cycle has happended, then return false; + + Implementation: + Use a node, track value, sequence number, and if visited, and its child nodes. + In DFS: first mark curr node visited, then DFS on child, then mark curr node with a sequence number. + Cycle: if a node has been visited but does not have a sequence number yet , + (that means some nodes at the earlier level, which has no been back-tracking to yet) + then there must be a cycle backwards. +*/ +public class Solution { + public class Node { + int val; + int seq; + boolean visited; + ArrayList children; + public Node(int val){ + this.val = val; + this.visited = false; + this.children = new ArrayList(); + this.seq = -1; + } + } + public int n; + public boolean canFinish(int numCourses, int[][] prerequisites) { + if (numCourses <= 0 || prerequisites == null || prerequisites.length == 0 || + prerequisites[0] == null || prerequisites[0].length == 0) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < prerequisites.length; i++) { + Node node; + //Add curr nodes + if (map.containsKey(prerequisites[i][0])) { + node = map.get(prerequisites[i][0]); + } else { + node = new Node(prerequisites[i][0]); + } + node.children.add(prerequisites[i][1]); + map.put(node.val, node); + //Add Child nodes + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new Node(prerequisites[i][1])); + } + } + n = prerequisites.length; + for (int i = 0; i < prerequisites.length; i++) { + if (!DFS(prerequisites[i][0], map)) { + return false; + } + } + + return true; + } + + public boolean DFS(int val, HashMap map) { + Node node = map.get(val); + node.visited = true; + map.put(val, node); + + for (int child : node.children) { + if (map.get(child).visited && map.get(child).seq == -1) {//Check cycle + return false; + } else if (!map.get(child).visited) { + if(!DFS(child, map)){ + return false; + } + } + } + + node.seq = n--; + map.put(val, node); + return true; + } +} + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Java/Data Stream Median.java b/Java/Data Stream Median.java old mode 100644 new mode 100755 index 398f50d..976fe84 --- a/Java/Data Stream Median.java +++ b/Java/Data Stream Median.java @@ -1,7 +1,17 @@ +H + +把Input stream想成向上的山坡。山坡中间那点,自然就是median. + +前半段,作为maxHeap,关注点是PriorityQueue的峰点,也就是实际上的median. + +后半段,作为minHeap,正常的PriorityQueue。 开头是最小的。 + +Note:题目定义meadian = A[(n-1)/2],也就是说maxHeap需要和minHeap长度相等,或者多一个element,最后可以直接poll() and return. + +``` /* Numbers keep coming, return the median of numbers at every time a new number added. -Have you met this question in a real interview? Yes Example For numbers coming list: [1, 2, 3, 4, 5], return [1, 1, 2, 2, 3]. @@ -13,7 +23,9 @@ Total run time in O(nlogn). Clarification -What's the definition of Median? - Median is the number that in the middle of a sorted array. If there are n numbers in a sorted array A, the median is A[(n - 1) / 2]. For example, if A=[1,2,3], median is 2. If A=[1,19], median is 1. +What's the definition of Median? - Median is the number that in the middle of a sorted array. +If there are n numbers in a sorted array A, the median is A[(n - 1) / 2]. +For example, if A=[1,2,3], median is 2. If A=[1,19], median is 1. Tags Expand LintCode Copyright Heap Priority Queue @@ -60,3 +72,5 @@ public int compare(Integer x, Integer y) { return rst; } } + +``` \ No newline at end of file diff --git a/Java/Delete Digits.java b/Java/Delete Digits.java old mode 100644 new mode 100755 index a9eaa58..8dbe31c --- a/Java/Delete Digits.java +++ b/Java/Delete Digits.java @@ -1,5 +1,11 @@ +M + +数位靠前的,权值更大. 所以硬来把靠前的相对更大的(跟following digit相比)去掉。 + +``` /* -Given string A representative a positive integer which has N digits, remove any k digits of the number, the remaining digits are arranged according to the original order to become a new positive integer. +Given string A representative a positive integer which has N digits, remove any k digits of the number, +the remaining digits are arranged according to the original order to become a new positive integer. Find the smallest integer after remove k digits. @@ -13,6 +19,10 @@ Tags Expand Greedy LintCode Copyright +*/ + +/* + Attempt2,Thoughts: loop k times: each interation, find one digit to remove Rules: want to remove whatever digit at A[i] that's A[i] > A[i+1]. @@ -21,14 +31,9 @@ Well... thinking straight (attempt2) seems much easier to understand and to code Note: remember to remove the prefixing 0's -*/ +*/ public class Solution { - /** - *@param A: A positive integer which has N digits, A is a string. - *@param k: Remove k digits. - *@return: A string - */ public String DeleteDigits(String A, int k) { if (A == null || A.length() == 0 || k == 0) { return A; @@ -112,3 +117,5 @@ public static String DeleteDigits(String A, int k) { } } + +``` \ No newline at end of file diff --git a/Java/Delete Node in the Middle of Singly Linked List.java b/Java/Delete Node in the Middle of Singly Linked List.java old mode 100644 new mode 100755 index 355deb8..cac5705 --- a/Java/Delete Node in the Middle of Singly Linked List.java +++ b/Java/Delete Node in the Middle of Singly Linked List.java @@ -1,3 +1,8 @@ +E + +Just do it. Link curr.next to curr.next.next + +``` /* Implement an algorithm to delete a node in the middle of a singly linked list, given only access to that node. @@ -32,9 +37,11 @@ public class Solution { */ public void deleteNode(ListNode node) { if (node == null) { - return; + return; } node.val = node.next.val; node.next = node.next.next; } } + +``` \ No newline at end of file diff --git a/Java/Distinct Subsequences.java b/Java/Distinct Subsequences.java old mode 100644 new mode 100755 index 35cf479..eaecb5d --- a/Java/Distinct Subsequences.java +++ b/Java/Distinct Subsequences.java @@ -1,7 +1,14 @@ +H + +Not Done + +``` /* Given a string S and a string T, count the number of distinct subsequences of T in S. -A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). +A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) +of the characters without disturbing the relative positions of the remaining characters. +(ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). Example Given S = "rabbbit", T = "rabbit", return 3. @@ -18,29 +25,29 @@ Do it in O(n2) time and O(n) memory. Attempt2: Use DP. Okay, first I had no idea how to start, but here is a reference: http://blog.csdn.net/abcbc/article/details/8978146 First of all, Map out the number of existance of T in S in a 2D map: - 0 1 2 3 4 5 6 7 - --------------- - r a b b b i t -0| 1 1 1 1 1 1 1 1 -1| r 0 1 1 1 1 1 1 1 -2| a 0 0 1 1 1 1 1 1 -3| b 0 0 0 1 2 3 3 3 -4| b 0 0 0 0 1 3 3 3 -5| i 0 0 0 0 0 0 3 3 -6| t 0 0 0 0 0 0 0 3 + 0 1 2 3 4 5 6 7 + --------------- + r a b b b i t +0| 1 1 1 1 1 1 1 1 +1| r 0 1 1 1 1 1 1 1 +2| a 0 0 1 1 1 1 1 1 +3| b 0 0 0 1 2 3 3 3 +4| b 0 0 0 0 1 3 3 3 +5| i 0 0 0 0 0 0 3 3 +6| t 0 0 0 0 0 0 0 3 Use DP[T][S]. We realize: 1.DP[0][0] == 1; //Both null can be a match 2.DP[0][1 ~ S.length - 1] = 1;//First fow, when T=="", whatever S will have 1 subsequence: "" 3.DP[1 ~ T.length][0] = 0;// First column, when S=="", whatever T will not be subsequence of S == "" 4.When looking at each row and filling out the pixels, we realize when T exist in S[a~b], it will surely exist in S[a~b+1], taht is: - Step1: DP[i][j] is at least equal to DP[i][j - 1];//DP[i][j] is always based on DP[i][j-1], so DP[i][j] = DP[i][j+1] + something - Step2: So, what's that 'something' in step1? For example, look at T[3] == 'b' against S[0 ~ 3]: - S[0 ~ 3] has 1 'b' at S[3], and also, T[0~3] == S[0~3], that's a perfect match. SO DP[3][3] = 1 - S[0 ~ 4] has 2 'b' at S[3] and S[4]. Now imagine we pick either S[3] or S[4] to genreate T[0~3] out of S[0~4]: we have 2 possibilities.D[3][4] = 2 - Consider: D[i][j] means we picked S[j]; in our S[0 ~ 4] case, that means we picked S[4] but skipped S[3], though S[3] still counts towards another situation where we skipped S[4]. - After all, we will count whatever that we skipped into our current DP[i][j], that is DP[i][j] += T[i - 1] == S[j - 1] ? DP[i - 1][j - 1] : 0; - Conclusion: while we for-looping through each row, if we find out S[j] and S[j - 1] both equals to T[i - 1], we want to make sure we count D[i - 1][j -1]'s previous records in! + Step1: DP[i][j] is at least equal to DP[i][j - 1];//DP[i][j] is always based on DP[i][j-1], so DP[i][j] = DP[i][j+1] + something + Step2: So, what's that 'something' in step1? For example, look at T[3] == 'b' against S[0 ~ 3]: + S[0 ~ 3] has 1 'b' at S[3], and also, T[0~3] == S[0~3], that's a perfect match. SO DP[3][3] = 1 + S[0 ~ 4] has 2 'b' at S[3] and S[4]. Now imagine we pick either S[3] or S[4] to genreate T[0~3] out of S[0~4]: we have 2 possibilities.D[3][4] = 2 + Consider: D[i][j] means we picked S[j]; in our S[0 ~ 4] case, that means we picked S[4] but skipped S[3], though S[3] still counts towards another situation where we skipped S[4]. + After all, we will count whatever that we skipped into our current DP[i][j], that is DP[i][j] += T[i - 1] == S[j - 1] ? DP[i - 1][j - 1] : 0; + Conclusion: while we for-looping through each row, if we find out S[j] and S[j - 1] both equals to T[i - 1], we want to make sure we count D[i - 1][j -1]'s previous records in! Note: In double for loop, set i,j <= xxxx.length(), since we've increased the 2D array by 1 block on row and col. @@ -53,23 +60,23 @@ public class Solution { * @return: Count the number of distinct subsequences */ public int numDistinct(String S, String T) { - int[][] DP = new int[T.length() + 1][S.length() + 1]; - DP[0][0] = 1; - for(int i = 1; i < S.length(); i++) { - DP[0][i] = 1; - } - for (int i = 1; i < T.length(); i++) { - DP[i][0] = 0; - } - for (int i = 1; i <= T.length(); i++) { - for (int j = 1; j <= S.length(); j++){ - DP[i][j] = DP[i][j - 1]; - if (T.charAt(i - 1) == S.charAt(j - 1)) { - DP[i][j] += DP[i - 1][j - 1]; - } - } - } - return DP[T.length()][S.length()]; + int[][] DP = new int[T.length() + 1][S.length() + 1]; + DP[0][0] = 1; + for(int i = 1; i < S.length(); i++) { + DP[0][i] = 1; + } + for (int i = 1; i < T.length(); i++) { + DP[i][0] = 0; + } + for (int i = 1; i <= T.length(); i++) { + for (int j = 1; j <= S.length(); j++){ + DP[i][j] = DP[i][j - 1]; + if (T.charAt(i - 1) == S.charAt(j - 1)) { + DP[i][j] += DP[i - 1][j - 1]; + } + } + } + return DP[T.length()][S.length()]; } } @@ -81,19 +88,19 @@ public int numDistinct(String S, String T) { */ public class Solution { public int numDistinct(String S, String T) { - if (S.length() == 0) { - return T.length() == 0 ? 1 : 0; - } - if (T.length() == 0) { - return 1; - } - int count = 0; - for (int i = 0; i < S.length(); i++) { - if (S.charAt(i) == T.charAt(0)) { - count += numDistinct(S.substring(i + 1), T.substring(1)); - } - } - return count; + if (S.length() == 0) { + return T.length() == 0 ? 1 : 0; + } + if (T.length() == 0) { + return 1; + } + int count = 0; + for (int i = 0; i < S.length(); i++) { + if (S.charAt(i) == T.charAt(0)) { + count += numDistinct(S.substring(i + 1), T.substring(1)); + } + } + return count; } } @@ -107,4 +114,5 @@ public int numDistinct(String S, String T) { However, time cost on this: For example I have n missing chars from S.length == m. so I have (m + 1) places where i can insert the n chars. Then it's a mCn problem. This goes up to m!, too much. Not applicapable. -*/ \ No newline at end of file +*/ +``` \ No newline at end of file diff --git a/Java/Edit Distance.java b/Java/Edit Distance.java old mode 100644 new mode 100755 index 916b78f..d13b9ee --- a/Java/Edit Distance.java +++ b/Java/Edit Distance.java @@ -1,5 +1,11 @@ +M + +Not Done + +``` /* -Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) +Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. +(each operation is counted as 1 step.) You have the following 3 operations permitted on a word: @@ -27,10 +33,6 @@ DP[i][j] means the steps (edit distance) to take to transfer word1[0 ~ i] to wor public class Solution { - /** - * @param word1 & word2: Two string. - * @return: The minimum number of steps. - */ public int minDistance(String word1, String word2) { if (word1 == null && word2 != null) { return word2.length(); @@ -56,3 +58,5 @@ public int minDistance(String word1, String word2) { return DP[word1.length()][word2.length()]; } } + +``` \ No newline at end of file diff --git a/Java/Encode and Decode Strings.java b/Java/Encode and Decode Strings.java new file mode 100755 index 0000000..2e9245c --- /dev/null +++ b/Java/Encode and Decode Strings.java @@ -0,0 +1,153 @@ +M + +方法1: +用数字+"#"+string来encode. +基于我们自己定的规律, 在decode的里面不需要过多地去check error input, assume所有input都是规范的. +decode就是找"#",然后用"#"前的数字截取后面的string. + + + +Old Solution: +Cast character into int. 串联起来, seperate by "LINE". +handle empty list [], or just null: 要把Null特别mark一下为‘NULL’, 这样decode时才能check到。 adminadmin + + +``` +/* +Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings. + +Machine 1 (sender) has the function: + +string encode(vector strs) { + // ... your code + return encoded_string; +} +Machine 2 (receiver) has the function: +vector decode(string s) { + //... your code + return strs; +} +So Machine 1 does: + +string encoded_string = encode(strs); +and Machine 2 does: + +vector strs2 = decode(encoded_string); +strs2 in Machine 2 should be the same as strs in Machine 1. + +Implement the encode and decode methods. + +Note: +The string may contain any possible characters out of 256 valid ascii characters. Your algorithm should be generalized enough to work on any possible characters. +Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless. +Do not rely on any library method such as eval or serialize methods. You should implement your own encode/decode algorithm. + + +Tags: String +Similar Problems: (E) Count and Say, (M) Serialize and Deserialize Binary Tree + +*/ + + +/* +Recap 3.28.2016 +Use number+"#" to mark a string. Append them all. +*/ +public class Codec { + + // Encodes a list of strings to a single string. + public String encode(List strs) { + if (strs.size() == 0) { + return ""; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < strs.size(); i++) { + sb.append(strs.get(i).length() + "#" + strs.get(i)); + } + return sb.toString(); + } + + // Decodes a single string to a list of strings. + public List decode(String s) { + List strs = new ArrayList(); + if (s == null || s.length() == 0) { + return strs; + } + int start = 0; + while (start < s.length()) { + int ind = s.indexOf("#", start); + int leng = Integer.parseInt(s.substring(start, ind)); + + start = ind + 1 + leng; + strs.add(s.substring(ind + 1, start)); + + } + return strs; + } +} + + +/* +Thoughts: +Break into integers +Use some special words to: 1. break line. 2. record null condition. +Note: "" empty string is also a string case, so don't treat that as null. Call null, "NULL" +Note2: As long as the list is not empty, though some string might be just "", make sure to encode it as 'LINE' just to remind in decoder: treat it as a "" +*/ +public class Codec { + // Encodes a list of strings to a single string. + public static String encode(List strs) { + if (strs == null || strs.size() == 0) { + return "NULL"; + } + StringBuffer sb = new StringBuffer(); + for (String str : strs) { + char[] arr = str.toCharArray(); + for (int i = 0; i < arr.length; i++) { + if (arr[i] >= 100) { + sb.append("" + (int)arr[i]); + } else if (arr[i] >= 10) { + sb.append("0" + (int)arr[i]); + } else { + sb.append("00" + (int)arr[i]); + } + } + sb.append("LINE"); + }//END for + if (sb.length() == 0) { + sb.append("LINE"); + } + return sb.toString(); + } + + // Decodes a single string to a list of strings. + public static List decode(String s) { + List rst = new ArrayList(); + if (s.equals("NULL")) { + return rst; + } + int index = s.indexOf("LINE"); + while (index != -1) { + String str = s.substring(0, index); + + StringBuffer sb = new StringBuffer(); + int i = 0; + while (i + 3 <= str.length()) { + int letter = Integer.parseInt(str.substring(i, i + 3)); + sb.append((char)letter); + i+=3; + } + rst.add(sb.toString()); + + s = s.substring(index + 4); + index = s.indexOf("LINE"); + } + + return rst; + } +} +// Your Codec object will be instantiated and called as such: +// Codec codec = new Codec(); +// codec.decode(codec.encode(strs)); + +``` \ No newline at end of file diff --git a/Java/ExcelSheetColumnNumber .java b/Java/ExcelSheetColumnNumber .java new file mode 100755 index 0000000..c00c906 --- /dev/null +++ b/Java/ExcelSheetColumnNumber .java @@ -0,0 +1,50 @@ +E + +'A' - 'A' = 0. 所以 char - 'A' + 1 = 题目里的对应数位。 +26位运算和10位一样嘛,num += 每位的digit * Math.pow(26, 数位号)。 + + +``` +/* +Given a column title as appear in an Excel sheet, return its corresponding column number. + +For example: + + A -> 1 + B -> 2 + C -> 3 + ... + Z -> 26 + AA -> 27 + AB -> 28 +*/ + + +public class Solution {//ABC -> 'A', 'B', 'C' + public int titleToNumber(String s) {//S = AA + int rst = 0; + char[] arr = s.toCharArray(); + for (int i = 0; i < arr.length; i++) {//i = 0,1,2 // (char c : arr) + rst = rst * 26 + arr[i] - 'A' + 1;//rst =1, 26 + 1 = 27, + } + return rst; + } +} + +//3.4.2016 recap +//digit * pow(26, digit position) +public class Solution { + public int titleToNumber(String s) { + if (s == null || s.length() == 0) { + return 0; + } + int num = 0; + for (int i = s.length() - 1; i >= 0; i--) { + int digit = s.charAt(i) - 'A' + 1; + num += digit * Math.pow(26, s.length() - i - 1); + } + return num; + } +} + +``` \ No newline at end of file diff --git a/Java/Expression Evaluation.java b/Java/Expression Evaluation.java old mode 100644 new mode 100755 index 47df6b5..54aac1e --- a/Java/Expression Evaluation.java +++ b/Java/Expression Evaluation.java @@ -1,10 +1,15 @@ -Build Expression Tree的另外一个变形。 -做的还是PostTraversal。先eval left, right, 然后eval符号。 +H + +Build Expression Tree的另外一个变形,依然Min Tree. + +build好Min Tree以后,做PostTraversal. Divde and Conquer: +先recursively找到 left和right的大小, 然后evaluate中间的符号。 + +Note: +1. Handle数字时,若left&&right Child全Null,那必定是我们weight最大的数字node了。 +2. 若有个child是null,那就return另外一个node。 +3. prevent Integer overflow during operation:过程中用个Long,最后结局在cast back to int. -注意Handle数字时,若左右Child全Null,那必定是我们weight最大的数字node了。 -若有个child是null,那就return另外一个node。 -还要注意: -过程中用个Long吧,最后结局在cast back to int. ``` /* Given an expression string array, return the final result of this expression diff --git a/Java/Expression Tree Build.java b/Java/Expression Tree Build.java old mode 100644 new mode 100755 index 795d3be..544788e --- a/Java/Expression Tree Build.java +++ b/Java/Expression Tree Build.java @@ -1,9 +1,59 @@ +H + 和Max-tree一样,感谢http://blog.welkinlan.com/2015/06/29/max-tree-lintcode-java/ -这个题目是Min-tree, 头上最小,Logic 和max-tree如出一辙。 -注意虚拟的形态:treeNode,作用就是为了有个weight,好排序。 -要想想,Java这个strict mom,如果换做JavaScript, 直接在expressionTreeNode上面附加一个object就完了,哪还用什么另外一个TreeNode class. -O(n) + +这个题目是Min-tree, 头上最小,Logic 和max-tree如出一辙 + +注意treeNode,为了帮助ExpressionTreeNode 排序。它加了一个weight based on expression,协助build Min-Tree 排序。 + +Space: O(n) +Time on average: O(n). + ``` +/* + +The structure of Expression Tree is a binary tree to evaluate certain expressions. +All leaves of the Expression Tree have an number string value. +All non-leaves of the Expression Tree have an operator string value. + +Now, given an expression array, build the expression tree of this expression, return the root of this expression tree. + +Example +For the expression (2*6-(23+7)/(1+2)) (which can be represented by ["2" "*" "6" "-" "(" "23" "+" "7" ")" "/" "(" "1" "+" "2" ")"]). +The expression tree will be like + + [ - ] + / \ + [ * ] [ / ] + / \ / \ + [ 2 ] [ 6 ] [ + ] [ + ] + / \ / \ + [ 23 ][ 7 ] [ 1 ] [ 2 ] . +After building the tree, you just need to return root node [-]. + +Clarification +See wiki: +Expression Tree + +Tags Expand +LintCode Copyright Stack Binary Tree + + +*/ + +/** + * Definition of ExpressionTreeNode: + * public class ExpressionTreeNode { + * public String symbol; + * public ExpressionTreeNode left, right; + * public ExpressionTreeNode(String symbol) { + * this.symbol = symbol; + * this.left = this.right = null; + * } + * } + */ + + public class Solution { class TreeNode { int val; diff --git a/Java/Fast Power.java b/Java/Fast Power.java old mode 100644 new mode 100755 index dca7b79..385ad5b --- a/Java/Fast Power.java +++ b/Java/Fast Power.java @@ -1,3 +1,15 @@ +M + +a^n可以被拆解成(a*a*a*a....*a), 是乘机形式,而%是可以把每一项都mod一下的。所以就拆开来take mod. + +这里用个二分的方法,recursively二分下去,直到n/2为0或者1,然后分别对待. + +注意1: 二分后要conquer,乘积可能大于Integer.MAX_VALUE, 所以用个long. + +注意2: 要处理n%2==1的情况,二分时候自动省掉了一份,要乘一下。 + + +``` /* Calculate the a^n % b where a, b and n are all 32bit integers. @@ -12,6 +24,10 @@ Tags Expand Divide and Conquer + +*/ + +/* Thoughts: Learn online: (a * b) % p = (a % p * b % p) % p @@ -19,27 +35,28 @@ Note: when n is odd number, it cannot be evenly divided into n/2 and n/2. This case needs special treatment: n = n/2 + n/2 + 1; */ - class Solution { /* * @param a, b, n: 32bit integers * @return: An integer */ public int fastPower(int a, int b, int n) { - if (n == 0) { - return 1 % b; - } - if (n == 1) { - return a % b; - } + if (n == 0) { + return 1 % b; + } + if (n == 1) { + return a % b; + } - long recurPow = fastPower(a, b, n / 2); - recurPow = (recurPow * recurPow) % b; + long recurPow = fastPower(a, b, n / 2); + recurPow = (recurPow * recurPow) % b; - if (n % 2 == 1) { - recurPow = recurPow * a % b; - } + if (n % 2 == 1) { + recurPow = recurPow * a % b; + } - return (int)recurPow; + return (int)recurPow; } }; + +``` \ No newline at end of file diff --git a/Java/Fibonacci.java b/Java/Fibonacci.java old mode 100644 new mode 100755 index adf73eb..237fcbc --- a/Java/Fibonacci.java +++ b/Java/Fibonacci.java @@ -1,3 +1,13 @@ +E + +方法1: DP array. + +方法1.1: 滚动数组, 简化DP。 + +方法2: recursively calculate fib(n - 1) + fib(n - 2). 公式没问题, 但是时间太长, timeout. + + +``` /* Find the Nth number in Fibonacci sequence. @@ -23,27 +33,65 @@ Tags Expand Enumeration Mathematics Non Recursion + +*/ +/* + Recap 3.28.2016. + Rolling array, instead of initiating array. +*/ +class Solution { + public int fibonacci(int n) { + if (n <= 1) { + return 0; + } + int first = 0; + int second = 1; + for (int i = 2; i < n; i++) { + int temp = second; + second = first + second; + first = temp; + } + return second; + } +} + + +/* Thoughts: 1. If non-recursion, do for loop for that n 2. Note: this specfiic problem is not 0-based. it's 1-based. 3. return fib[n] */ - class Solution { - /** - * @param n: an integer - * @return an integer f(n) - */ public int fibonacci(int n) { if (n <= 1) { - return 0; + return 0; } - int[] fib = new int[n + 1]; - fib[1] = 0; - fib[2] = 1; - for (int i = 3; i <= n; i++) { - fib[i] = fib[i - 1] + fib[i - 2]; + int[] fib = new int[n]; + fib[0] = 0; + fib[1] = 1; + for (int i = 2; i < n; i++) { + fib[i] = fib[i - 1] + fib[i - 2]; } - return fib[n]; + return fib[n - 1]; } } + + +/* + Recursive. Long time complexity + Timeout +*/ +class Solution { + public int fibonacci(int n) { + if (n <= 1) { + return 0; + } + if (n == 2) { + return 1; + } + return fibonacci(n - 1) + fibonacci(n - 2); + } +} + +``` \ No newline at end of file diff --git a/Java/Find the Connected Component in the Undirected Graph.java b/Java/Find the Connected Component in the Undirected Graph.java index 694d25c..2a8bcc2 100644 --- a/Java/Find the Connected Component in the Undirected Graph.java +++ b/Java/Find the Connected Component in the Undirected Graph.java @@ -1,12 +1,15 @@ -BFS遍历,把每个node的neighbor都加进来。 +M + +BFS遍历,把每个node的neighbor都加进来。 -一定注意要把visit过的node Mark一下。因为curr node也会是别人的neighbor,会无限循环。 +一定注意要把visit过的node Mark一下。因为curr node也会是别人的neighbor,会无限循环。 -Component的定义:所有Component内的node必须被串联起来via path (反正这里是undirected, 只要链接上就好) +Component的定义:所有Component内的node必须被串联起来via path (反正这里是undirected, 只要链接上就好) -这道题:其实component在input里面都已经给好了,所有能一口气visit到的,全部加进queue里面,他们就是一个component里面的了。 +这道题:其实component在input里面都已经给好了,所有能一口气visit到的,全部加进queue里面,他们就是一个component里面的了。 + +而我们这里不需要判断他们是不是Component。 -而我们这里不需要判断他们是不是Component。 ``` /* Find the number connected component in the undirected graph. diff --git a/Java/Find the Weak Connected Component in the Directed Graph.java b/Java/Find the Weak Connected Component in the Directed Graph.java index 34f0384..a898ee7 100644 --- a/Java/Find the Weak Connected Component in the Directed Graph.java +++ b/Java/Find the Weak Connected Component in the Directed Graph.java @@ -1,16 +1,19 @@ -Identify这是个union-find问题还挺巧妙。 -看到了weak component的形式: 一个点指向所有,那么所有的点都有一个公共的parent,然后就是要找出这些点。 +M -为何不能从一个点出发,比如A,直接print它所有的neighbors呢? - 不行,如果轮到了B点,那因为是directed,它也不知道A的情况,也不知道改如何继续加,或者下手。 +Identify这是个union-find问题还挺巧妙。 +看到了weak component的形式: 一个点指向所有,那么所有的点都有一个公共的parent,然后就是要找出这些点。 -所以,要把所有跟A有关系的点,或者接下去和A的neighbor有关系的点,都放进union-find里面,让这些点有Common parents. +为何不能从一个点出发,比如A,直接print它所有的neighbors呢? + 不行,如果轮到了B点,那因为是directed,它也不知道A的情况,也不知道改如何继续加,或者下手。 + +所以,要把所有跟A有关系的点,或者接下去和A的neighbor有关系的点,都放进union-find里面,让这些点有Common parents. + +最后output的想法: +做一个 map 。 +之前我们不是给每个num都存好了parent了嘛。 +每个num都有个parent, 然后不同的parent就创造一个不同的list。 +最后,把Map里面所有的list拿出来就好了。 -最后output的想法: -做一个 map 。 -之前我们不是给每个num都存好了parent了嘛。 -每个num都有个parent, 然后不同的parent就创造一个不同的list。 -最后,把Map里面所有的list拿出来就好了。 ``` /* Find the number Weak Connected Component in the directed graph. diff --git a/Java/First Bad Version.java b/Java/First Bad Version.java index 3a13b36..33dc5ad 100644 --- a/Java/First Bad Version.java +++ b/Java/First Bad Version.java @@ -1,5 +1,10 @@ -根据isBadVersion的性质,判断还如何end=mid or start=mid. +M + +Binary Search + +根据isBadVersion的性质,判断还如何end=mid or start=mid. isBadVersion 是有方向的嘛,一个点错了,后面全错。 + ``` /* The code base version is an integer start from 1 to n. @@ -10,7 +15,7 @@ You can call isBadVersion to help you determine which version is the first bad one. The details interface can be found in the code's annotation part. -Have you met this question in a real interview? Yes + Example Given n = 5: @@ -43,10 +48,6 @@ * the kth code version is bad or not. */ class Solution { - /** - * @param n: An integers. - * @return: An integer which is the first bad version. - */ public int findFirstBadVersion(int n) { if (n < 1) { return 0; diff --git a/Java/Flatten 2D Vector.java b/Java/Flatten 2D Vector.java new file mode 100644 index 0000000..10cfaee --- /dev/null +++ b/Java/Flatten 2D Vector.java @@ -0,0 +1,82 @@ +/* +Implement an iterator to flatten a 2d vector. + +For example, +Given 2d vector = + +[ + [1,2], + [3], + [4,5,6] +] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]. + +Hint: + +How many variables do you need to keep track? +Two variables is all you need. Try with x and y. +Beware of empty rows. It could be the first few rows. +To write correct code, think about the invariant to maintain. What is it? +The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? +Not sure? Think about how you would implement hasNext(). Which is more complex? +Common logic in two different places should be refactored into a common method. + + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Zigzag Iterator, (M) Peeking Iterator + +*/ + +/* +Thoughts: +As hint indicates: use 2 pointers to hold position. +Use hasNext to validate (x,y) and move x. +Use next() to return (x,y) and move it(regardless of correctness, which is determined by hasNext()) +*/ +public class Vector2D { + private int x; + private int y; + private List> list; + public Vector2D(List> vec2d) { + if (vec2d == null) { + return; + } + this.x = 0; + this.y = 0; + this.list = vec2d; + } + + public int next() { + int rst = list.get(x).get(y); + if (y + 1 >= list.get(x).size()) { + y = 0; + x++; + } else { + y++; + } + return rst; + } + + public boolean hasNext() { + if (list == null) { + return false; + } + while (x < list.size() && list.get(x).size() == 0) { + x++; + y = 0; + } + if (x >= list.size()) { + return false; + } + if (y >= list.get(x).size()) { + return false; + } + return true; + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D i = new Vector2D(vec2d); + * while (i.hasNext()) v[f()] = i.next(); + */ \ No newline at end of file diff --git a/Java/Flatten Binary Tree to Linked List.java b/Java/Flatten Binary Tree to Linked List.java index 6ff61e1..88a5acc 100644 --- a/Java/Flatten Binary Tree to Linked List.java +++ b/Java/Flatten Binary Tree to Linked List.java @@ -1,3 +1,9 @@ +E + +Not Done + + +``` /* Flatten Binary Tree to Linked List @@ -48,19 +54,19 @@ public class Solution { */ public TreeNode parentNode = null; public void flatten(TreeNode root) { - if (root == null) { - return; - } - - if (parentNode != null) { - parentNode.left = null; - parentNode.right = root; - } - - parentNode = root; - TreeNode right = root.right; - flatten(root.left); - flatten(right); + if (root == null) { + return; + } + + if (parentNode != null) { + parentNode.left = null; + parentNode.right = root; + } + + parentNode = root; + TreeNode right = root.right; + flatten(root.left); + flatten(right); } } @@ -80,3 +86,5 @@ public void flatten(TreeNode root) { + +``` \ No newline at end of file diff --git a/Java/Flattern 2D Vector.java b/Java/Flattern 2D Vector.java new file mode 100644 index 0000000..cc01237 --- /dev/null +++ b/Java/Flattern 2D Vector.java @@ -0,0 +1,88 @@ +大概意思就是把2D list里面的element全部遍历一遍。 +注意啊,一开始理解题意搞错:我以为是必须要排序正确,所以上来就PriorityQueue+HashMap搞得无比复杂。其实,这个跟一个nxn的matrix遍历,是没区别的拉。 +所有来个x,y,把2d list跑一变。 + +``` +/* +Implement an iterator to flatten a 2d vector. + +For example, +Given 2d vector = + +[ + [1,2], + [3], + [4,5,6] +] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]. + +Hint: + +How many variables do you need to keep track? +Two variables is all you need. Try with x and y. +Beware of empty rows. It could be the first few rows. +To write correct code, think about the invariant to maintain. What is it? +The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? +Not sure? Think about how you would implement hasNext(). Which is more complex? +Common logic in two different places should be refactored into a common method. + + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Zigzag Iterator, (M) Peeking Iterator + +*/ + +/* +Thoughts: +As hint indicates: use 2 pointers to hold position. +Use hasNext to validate (x,y) and move x. +Use next() to return (x,y) and move it(regardless of correctness, which is determined by hasNext()) +*/ +public class Vector2D { + private int x; + private int y; + private List> list; + public Vector2D(List> vec2d) { + if (vec2d == null) { + return; + } + this.x = 0; + this.y = 0; + this.list = vec2d; + } + + public int next() { + int rst = list.get(x).get(y); + if (y + 1 >= list.get(x).size()) { + y = 0; + x++; + } else { + y++; + } + return rst; + } + + public boolean hasNext() { + if (list == null) { + return false; + } + while (x < list.size() && list.get(x).size() == 0) { + x++; + y = 0; + } + if (x >= list.size()) { + return false; + } + if (y >= list.get(x).size()) { + return false; + } + return true; + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D i = new Vector2D(vec2d); + * while (i.hasNext()) v[f()] = i.next(); + */ +``` \ No newline at end of file diff --git a/Java/Flip Game II.java b/Java/Flip Game II.java new file mode 100644 index 0000000..3fb9bff --- /dev/null +++ b/Java/Flip Game II.java @@ -0,0 +1,171 @@ +12.06.2015 recap: +注意:不要乱改input s. recursive call 需要用原始的input s. + +这个题目李特是屌炸天的。 +我飞了九牛二虎之力(路子对),但是代码写的七荤八素,好长好长好长好长的。 +结果正解,三四行就搞定了。真是心有不甘啊。 +想法如下: +保证p1能胜利,就必须保持所有p2的move都不能赢。 +同时,p1只要在可走的Move里面,有一个move可以赢就足够了。 +(题目里面用一个for loop + 只要 满足条件就return true来表达 OR的意思:p1不同的路子,赢一种就行了) +p1: player1 +p2: player2 + +``` +/* +You are playing the following Flip Game with your friend: +Given a string that contains only these two characters: + and -, +you and your friend take turns to flip two consecutive "++" into "--". +The game ends when a person can no longer make a move and therefore the other person will be the winner. + +Write a function to determine if the starting player can guarantee a win. + +For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+". + +Follow up: +Derive your algorithm's runtime complexity. + +Tags: Backtracking +Similar Problems: (E) Nim Game, (E) Flip Game +*/ + +/* + recap: 12.06.2015 + Make sure to use a new string, and do not alter the original input s when calling recursively on canWin. +*/ + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + String str = new String(s); + while (str.indexOf("++") != -1) { + int index = str.indexOf("++"); + if(!canWin(s.substring(0, index) + "--" + s.substring(index + 2))) { + return true; + } + str = str.substring(0, index) + "-" + str.substring(index + 1); + } + return false; + } + +} + + + +/* +Attemp2, from:http://www.cnblogs.com/jcliBlogger/p/4886741.html +Similar to my idea, but much more clear: no need of the isP1 flag. +Iterative idea:p1 can win, and p2 must not win at all. +Therefore, if p2's move can't win, we return true on p1's state. +For loop and the if statement works as 'OR': just need one of the p1's movement win. +*/ + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (!canWin( s.substring(0, i) + "--" + s.substring(i + 2))) {//Just pick one way of p1's move + return true; + } + str = str.substring(0, i) + "-" + str.substring(i + 1);//Help to move certain spot. + } + return false; + } + +} +//let k = n/2 +//O(k * (k - 1) * (k - 2) ... k) = O(k!) = O((n/2)!) = O(n!) + +/* +Attempt1, Failed. +Thoughts: +method checkP1Win(), inside of it: +OR all p1's win state, if one of the move wins, return true; +However, a bit of code redundancy, does not feel good about this. +Fails on "+++++++++" +*/ +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + boolean rst = false; + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (checkP1Win(s, i, true)) { + rst = true; + break; + } + str = str.substring(0, i) + "-" + str.substring(i + 1); + } + return rst; + + } + public static boolean checkP1Win(String str, int x, boolean isP1) { + String s = str.substring(0,x) + "--" + str.substring(x + 2); + if (s.indexOf("++") == -1) { + return isP1; + } + for (int i = s.indexOf("++"); i >= 0 && i < s.length() - 1; i = s.indexOf("++")) { + if (checkP1Win(s, i, !isP1)) { + return true; + } + s = s.substring(0, i) + "-" + s.substring(i + 1); + } + return false; + } + + +} + + + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + boolean rst = false; + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (checkP1Win(s, i, true)) { + rst = true; + break; + } + str = str.substring(0, i) + "-" + str.substring(i + 1); + } + return rst; + + } + public static boolean checkP1Win(String str, int x, boolean isP1) { + String s = str.substring(0,x) + "--" + str.substring(x + 2); + if (s.indexOf("++") == -1) { + return isP1; + } + if (isP1) { + String temp = s; + for (int i = temp.indexOf("++"); i >= 0 && i < temp.length() - 1; i = temp.indexOf("++")) { + if (checkP1Win(s, i, !isP1)) { + return true; + } + temp = temp.substring(0, i) + "-" + temp.substring(i + 1); + } + return false; + } else { + String temp = s; + for (int i = temp.indexOf("++"); i >= 0 && i < temp.length() - 1; i = temp.indexOf("++")) { + if (!checkP1Win(s, i, !isP1)) { + return false; + } + temp = temp.substring(0, i) + "-" + temp.substring(i + 1); + } + return true; + } + } +} +``` \ No newline at end of file diff --git a/Java/Flip Game.java b/Java/Flip Game.java new file mode 100644 index 0000000..2afa5c1 --- /dev/null +++ b/Java/Flip Game.java @@ -0,0 +1,78 @@ +这个题目是很寂寞的. 2 pointer可以做, 在网上又搜了一下,貌似可以有很多牛逼的优化,我暂时还没去看。 +很郁闷的就是条件不明,原来只需要从'++'转到'--'的情况,反过来没必要关注...搞了我半天啊 +``` +/* +You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner. + +Write a function to compute all possible states of the string after one valid move. + +For example, given s = "++++", after one move, it may become one of the following states: + +[ + "--++", + "+--+", + "++--" +] +*/ + +// 12.06.2015, slower than the previous one +public class Solution { + public List generatePossibleNextMoves(String s) { + List rst = new ArrayList(); + if (s == null || s.length() == 0) { + return rst; + } + ArrayList list = new ArrayList(); + StringBuffer sb = new StringBuffer(s); + while (sb.indexOf("++") != -1) { + int index = sb.indexOf("++"); + list.add(index); + sb.replace(index, index + 1, "*"); + } + for (int index : list) { + rst.add(s.substring(0, index) + "--" + s.substring(index + 2)); + } + return rst; + } +} + + +/* +Thoughts: +Two pointers to check if p1 and p2 match target patern. If so, add. + +Need to ask: are we only looking to change to '--' from '++'? +*/ +public class Solution { + public static List generatePossibleNextMoves(String s) { + List rst = new ArrayList(); + if (s == null || s.length() < 1) { + return rst; + } + char[] arr = s.toCharArray(); + search('+','-',arr,rst); + return rst; + } + + public static void search(char target, char replace, char[] arr, List rst) { + int p1 = 0; + int p2 = 1; + while (p2 <= arr.length - 1) { + if (arr[p1] == target && arr[p2] == target) { + arr[p1] = replace; + arr[p2] = replace; + rst.add(new String(arr)); + arr[p1] = target; + arr[p2] = target; + } + p1++; + p2++; + } + } +} + + + + + +``` \ No newline at end of file diff --git a/Java/Fraction to Recurring Decimal.java b/Java/Fraction to Recurring Decimal.java new file mode 100644 index 0000000..d482da0 --- /dev/null +++ b/Java/Fraction to Recurring Decimal.java @@ -0,0 +1,121 @@ +不难想到处理除法:考虑正负,考虑小数点前后。主要是小数点以后的要着重考虑。 +很容易忽略的是integer的益处。 +``` +/* +Given two integers representing the numerator and denominator of a fraction, return the fraction in string format. + +If the fractional part is repeating, enclose the repeating part in parentheses. + +For example, + +Given numerator = 1, denominator = 2, return "0.5". +Given numerator = 2, denominator = 1, return "2". +Given numerator = 2, denominator = 3, return "0.(6)". + +Hide Company Tags Google +Show Tags +Hash Table Math + + +*/ + +/* + Thoughts: + Divide it into small pieces: + 1. d = 0, return null; + 2. n = 0 -> 0 + 3. mark negative. let n = abs(numerator), d = abs(denominator) + 4. consider front and end: + front = (int)sharp divide + end: build hashmap to track if the numerator*10 occurs. Once occurs again, return the remianing. + 5. based on sign, return results. + +Note: +Have to take int overflow INT_MAX, INT_MIN.... +*/ +//Optimized code: +public class Solution { + public String fractionToDecimal(int numerator, int denominator) { + long nume = Math.abs((long)numerator); + long deno = Math.abs((long)denominator); + String sign = (numerator < 0) ^ (denominator < 0) ? "-" : ""; + if (deno == 0) { + return ""; + } else if (nume == 0) { + return "0"; + } else if (nume % deno == 0) { + return sign + nume/deno + ""; + } + + HashMap map = new HashMap(); + StringBuffer rst = new StringBuffer(sign + nume/deno + "."); + long end = nume%deno * 10;//The decimal portion of the value, after decimal point + int i = 0; + while (end != 0){ + if (map.containsKey(end)) { + rst.insert(rst.indexOf(".") + map.get(end) + 1, "("); + rst.append(")"); + return rst.toString(); + } + rst.append(end/deno); + map.put(end, i++); + end = (end % deno) * 10; + } + return rst.toString(); + } +} + + + +//Original working version +public class Solution { + public String fractionToDecimal(int numerator, int denominator) { + long nume = Math.abs((long)numerator); + long deno = Math.abs((long)denominator); + String sign = (numerator < 0) ^ (denominator < 0) ? "-" : ""; + if (deno == 0) { + return ""; + } else if (nume == 0) { + return "0"; + } else if (nume % deno == 0) { + return sign + nume/deno + ""; + } + + String rst = sign + nume/deno + "."; + long end = nume%deno * 10; + + HashMap map = new HashMap(); + boolean repeat = false; + String endRepeat = ""; + int n = 0; + while (true){ + if (end == 0) { + break; + } else if (map.containsValue(end)) { + repeat = true; + break; + } + map.put(n++, end); + end = (end % deno) * 10; + } + + for (int i = 0; i < n; i++) { + if (repeat && map.get(i) == end) { + rst += "(" + map.get(i)/deno; + endRepeat = ")"; + repeat = false; + } else { + rst += map.get(i)/deno; + } + } + + return rst + endRepeat; + } +} + + + + + + +``` \ No newline at end of file diff --git a/Java/Game of Life.java b/Java/Game of Life.java new file mode 100644 index 0000000..2799713 --- /dev/null +++ b/Java/Game of Life.java @@ -0,0 +1,42 @@ +/* +According to the Wikipedia's article: +"The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970." + +Given a board with m by n cells, each cell has an initial state live (1) or dead (0). +Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules +(taken from the above Wikipedia article): + +Any live cell with fewer than two live neighbors dies, as if caused by under-population. +Any live cell with two or three live neighbors lives on to the next generation. +Any live cell with more than three live neighbors dies, as if by over-population.. +Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction. +Write a function to compute the next state (after one update) of the board given its current state. + +Follow up: +Could you solve it in-place? Remember that the board needs to be updated at the same time: +You cannot update some cells first and then use their updated values to update other cells. +In this question, we represent the board using a 2D array. + In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. + How would you address these problems? +Credits: +Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. + +Hide Company Tags Google TinyCo +Hide Tags Array +Hide Similar Problems (M) Set Matrix Zeroes + +*/ + +/* + Thoughts: + https://segmentfault.com/a/1190000003819277 + http://my.oschina.net/Tsybius2014/blog/514447 + build state machine. + take mod of 2 at the end. +*/ + +public class Solution { + public void gameOfLife(int[][] board) { + + } +} \ No newline at end of file diff --git a/Java/Graph Valid Tree.java b/Java/Graph Valid Tree.java index 18288cc..aed53f0 100644 --- a/Java/Graph Valid Tree.java +++ b/Java/Graph Valid Tree.java @@ -1,8 +1,12 @@ -复习Union-Find的另外一个种形式。 -题目类型:查找2个元素是不是在一个set里面。如果不在,false. 如果在,那就合并成一个set,共享parent. -存储的关键都是:元素相对的index上存着他的root parent. +M + +复习Union-Find的另外一个种形式。 +题目类型:查找2个元素是不是在一个set里面。如果不在,false. 如果在,那就合并成一个set,共享parent. +存储的关键都是:元素相对的index上存着他的root parent. 另一个union-find, 用hashmap的:http://www.lintcode.com/en/problem/find-the-weak-connected-component-in-the-directed-graph/ + + ``` /* Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), diff --git a/Java/Gray Code.java b/Java/Gray Code.java new file mode 100644 index 0000000..6c0622d --- /dev/null +++ b/Java/Gray Code.java @@ -0,0 +1,175 @@ +M + +题目蛋疼,目前只接受一种结果。 + +BackTracking + DFS: + Recursive helper里每次flip一个 自己/左边/右边. Flip过后还要恢复原样.遍历所有. + +曾用法(未仔细验证): +基本想法就是从一个点开始往一个方向走,每次flip一个bit, 碰壁的时候就回头走。 + +``` +/* + +The gray code is a binary numeral system where two successive values differ in only one bit. + +Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. + +For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: + +00 - 0 +01 - 1 +11 - 3 +10 - 2 +Note: +For a given n, a gray code sequence is not uniquely defined. + +For example, [0,2,3,1] is also a valid gray code sequence according to the above definition. + +For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that. + +Hide Company Tags Amazon +Hide Tags Backtracking + +*/ + + +//Another solution, 02.10.2016 using DFS +//generate order, output the numerical value of each binary code. Integer.parseInt("10101", 2). +//Start with n-bit char[] of 0's. Flip one bit at a time. +//Recursive helper. char[], index. Flip or not flip. DFS + +public class Solution { + public List grayCode(int n) { + List rst = new ArrayList(); + if (n < 0) { + return rst; + } else if (n == 0) { + rst.add(0); + return rst; + } + char[] list = new char[n]; + for (int i = 0; i < n; i++) { + list[i] = '0'; + } + helper(rst, list, n - 1); + + return rst; + } + + public void helper(List rst, char[] list, int index) { + + rst.add(Integer.parseInt(new String(list), 2)); + + //self + list[index] = list[index] == '0' ? '1' : '0'; + int num = Integer.parseInt(new String(list), 2); + if (!rst.contains(num)) { + helper(rst, list, index); + } + list[index] = list[index] == '0' ? '1' : '0'; + + //left + if (index -1 >= 0) { + list[index - 1] = list[index - 1] == '0' ? '1' : '0'; + num = Integer.parseInt(new String(list), 2); + if (!rst.contains(num)) { + helper(rst, list, index - 1); + } + list[index - 1] = list[index - 1] == '0' ? '1' : '0'; + } + + //right + if (index + 1 < list.length) { + list[index + 1] = list[index + 1] == '0' ? '1' : '0'; + num = Integer.parseInt(new String(list), 2); + if (!rst.contains(num)) { + helper(rst, list, index + 1); + } + list[index + 1] = list[index + 1] == '0' ? '1' : '0'; + } + } +} + + +/* + +Leetcode tags shows backtracking. That should be different approach than what I hvae below: + +*/ + +/* + +TRY: My code works for this run-through, however does not fit the OJ yet + +0 0 0 [start, noting happend, flip index 0] + +0 0 <-1 [move to flip left adjacent] + +0 <-1 1 [move to flip left adjacent] + +1-> 1 1 [move to flip right adjacent] + +1 0-> 1 [move to flip right adjacent] + +1 0 <-0 [move to flip left adjacent] + +1 <-1 0 [move to flip left adjacent] + +0 1 0 [done] + +Conclusion: hit the wall and flip the other direction. + +Every flip, add integer to list + +Convert the char[] to string, then Integer.parse(str, 2) to integer + +Simulate the steps: + +For example, when n = 3, step = n - 1. It takes 2 steps from right side to reach left side, it hits the wall and turn around. + +Now: + +1. Initialize char[] and add '000' + +2. do for loop on 1 ~ 2^n -2. last step '010' is stepped into, but no further action, so take 2^3 - 1 = 7 steps. + +*/ +public class Solution { + public List grayCode(int n) { + List rst = new ArrayList(); + if (n < 0) { + return rst; + } + char[] bits = new char[n]; + for (int i = 0; i < bits.length; i++) { + bits[i] = '0'; + } + String str = new String(bits); + if (n == 0) { + str = "0"; + } + rst.add(Integer.parseInt(str, 2)); + int step = n - 1; + boolean LR = true;//L: true; R: false + int steps = (int)Math.pow(2, n) - 1; + for (int i = 0; i < steps; i++) { + bits[step] = bits[step] == '0' ? '1' : '0'; + str = new String(bits); + rst.add(Integer.parseInt(str, 2)); + if (LR) { + step--; + } else { + step++; + } + if (step == (n - 1) || step == 0) {//Turn around + LR = !LR; + } + } + + return rst; + } +} + + +``` \ No newline at end of file diff --git a/Java/Group Anagrams.java b/Java/Group Anagrams.java new file mode 100755 index 0000000..1fe764e --- /dev/null +++ b/Java/Group Anagrams.java @@ -0,0 +1,170 @@ +M + +方法一: 60% + +和check anagram 想法一样:转化并sort char array,用来作为key。 + +把所有anagram 存在一起。注意结尾Collections.sort(). + +O(NKlog(K)), N = string[] length, k = longest word length + + +优化:80% ~ 97% + +用固定长度的char[26] arr 存每个字母的frequency; 然后再 new string(arr). +因为每个位子上的frequency的变化,就能构建一个unique的string + + +错误的示范: 尝试先sort input strs[],但是NlogN 其实效率更低. 13% + + +``` + +/* +Given an array of strings, group anagrams together. + +For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], +Return: + +[ + ["ate", "eat","tea"], + ["nat","tan"], + ["bat"] +] +Note: +For the return value, each inner list's elements must follow the lexicographic order. +All inputs will be in lower-case. +Hide Company Tags Amazon Bloomberg Uber Facebook +Hide Tags Hash Table String +Hide Similar Problems (E) Valid Anagram (E) Group Shifted Strings + +*/ + + + +/* + optmize1: + Use collectoins.sort() instead of Arrays.sort() in front + + 分析: + n: str[].length + p: parts: number of keys in hashmap + m: max string length + (n/p): average ['abc', 'cab', 'cba', ... etc] length + Collections.sort(...) : (n/p)log(n/p) * p = n*log(n/p) + + so, how large is n/p? + 1. p is small, -> result goes large + 2. p is large -> result goes Small + + overal: + n*m + n*log(n/p) + + If Arrays.sort(strs) at first: + n*m + nlogn + + Therefore, using Collections.sort() in this problem is faster than using Arrays.sort() in front. + + optimize2: + char[26] arr: [1,1,2,0,0,0,0,0,0,0,...] + new String(arr) -> key of hashmap + n * m + + optimize3: + If not necessary, we don't have to use map.entrySet(); + we can just use map.keySet(); It's faster + + for (Map.Entry> entry : map.entrySet()) { + Collections.sort(entry.getValue()); + rst.add(entry.getValue()); + } + + LEET CODE SPEED: 80% ~ 97% (25ms ~ 22ms) + + + +*/ +public class Solution { + public List> groupAnagrams(String[] strs) { + List> rst = new ArrayList>(); + if (strs == null || strs.length == 0) { + return rst; + } + + HashMap> map = new HashMap>(); + + for (int i = 0; i < strs.length; i++) { + String str = calcUniqueKey(strs[i]); + if (!map.containsKey(str)) { + map.put(str, new ArrayList()); + } + map.get(str).add(strs[i]); + } + + for(String key: map.keySet()){//FASTER + Collections.sort(map.get(key)); + rst.add(map.get(key)); + } + + return rst; + } + + public String calcUniqueKey(String s) { + char[] arr = new char[26]; + for (int i = 0; i < s.length(); i++) { + arr[s.charAt(i) - 'a'] += 1; + } + return new String(arr); + } +} + + +/* +Thoughts: +brutle force: save to Map O(n) space,time + +Store the anagram in a order list. Collections.sort it. MO(logM) + +Note: use Arrays.sort() to sort string. +Note2: can do (element : array, arraylist) in for loop + +*/ +public class Solution { + public List> groupAnagrams(String[] strs) { + List> rst = new ArrayList>(); + if (strs == null || strs.length == 0) { + return rst; + } + HashMap> map = new HashMap>(); + + for (int i = 0; i < strs.length; i++) { + char[] arr = strs[i].toCharArray(); + Arrays.sort(arr); + String str = new String(arr); + if (!map.containsKey(str)) { + map.put(str, new ArrayList()); + } + map.get(str).add(strs[i]); + } + /* + for (Map.Entry> entry : map.entrySet()) {//SLOW + Collections.sort(entry.getValue()); + rst.add(entry.getValue()); + } + */ + for(String key: map.keySet()){//FASTER + Collections.sort(map.get(key)); + rst.add(map.get(key)); + } + + return rst; + } +} + + + + + + + +``` \ No newline at end of file diff --git a/Java/Group Shifted Strings.java b/Java/Group Shifted Strings.java new file mode 100755 index 0000000..af774b1 --- /dev/null +++ b/Java/Group Shifted Strings.java @@ -0,0 +1,64 @@ +E + +相同shift规则的string, 能被推算到同一个零起始点,就是共同减去一个char,最后就相等。以此作为key,用HashMap。一目了然。 + +记得根据题目意思,一开始要String[] sort一下。 + +``` +/* +Given a string, we can "shift" each of its letter to its successive letter, for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence: + +"abc" -> "bcd" -> ... -> "xyz" +Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence. + +For example, given: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"], +Return: + +[ + ["abc","bcd","xyz"], + ["az","ba"], + ["acef"], + ["a","z"] +] +Note: For the return value, each inner list's elements must follow the lexicographic order. + +Hide Company Tags Google Uber +Hide Tags Hash Table String +Hide Similar Problems (M) Group Anagrams + +*/ + +//Reduce each string into initial state: with the char at index 0 equal to integer 0. Save it as key for hashmap +public class Solution { + public List> groupStrings(String[] strings) { + List> rst = new ArrayList>(); + if (strings == null || strings.length == 0) { + return rst; + } + Arrays.sort(strings); + HashMap> map = new HashMap>(); + + for (String s : strings) { + char[] arr = s.toCharArray(); + char head = arr[0]; + for (int i = 0; i < arr.length; i++) { + if (arr[i] - head < 0) { + arr[i] = (char)((arr[i] - head) + 26); + } else { + arr[i] = (char)(arr[i] - head); + } + } + String key = new String(arr); + if (!map.containsKey(key)) { + map.put(key, new ArrayList()); + } + map.get(key).add(s); + } + + for (Map.Entry> entry : map.entrySet()) { + rst.add(entry.getValue()); + } + return rst; + } +} +``` \ No newline at end of file diff --git a/Java/H-Index II.java b/Java/H-Index II.java new file mode 100644 index 0000000..ec03820 --- /dev/null +++ b/Java/H-Index II.java @@ -0,0 +1,59 @@ +H-index的一个优化。 +binary search +``` +/* +Follow up for H-Index: What if the citations array is sorted in ascending order? +Could you optimize your algorithm? +Hint: + +Expected runtime complexity is in O(log n) and the input is sorted. + +Hide Company Tags Facebook +Hide Tags Binary Search +Hide Similar Problems (M) H-Index + +*/ + +/* + citations[0,1,3,5,6] + look for a h, where x = N-h, arr[x] >= h + h is from right ot left. + We want to find smallest x that has arr[x] >= n-x + binary search: + start,mid,end + if match, keep going left until not able to + O(nLogN) +*/ + +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + int n = citations.length; + int start = 0; + int end = n - 1; + int mid; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (citations[mid] == n - mid) { + if (mid - 1 >= 0 && citations[mid - 1] == n - (mid-1)) { + end = mid; + } else { + return n - mid;// that is n - x + } + } else if (citations[mid] < n - mid) { + start = mid; + } else { + end = mid; + } + } + if (citations[start] >= n - start) { + return n - start; + } else if (citations[end] >= n - end) { + return n - end; + } + return 0; + } +} +``` \ No newline at end of file diff --git a/Java/H-Index.java b/Java/H-Index.java new file mode 100644 index 0000000..d062c09 --- /dev/null +++ b/Java/H-Index.java @@ -0,0 +1,111 @@ +例子写出来,发现可以sort以后按照定义搜索一遍。 nlogn. + 当然,搜索一遍时候可以优化,用binary search. 但是没意义,因为array.sort已经用了nlogn + +o(n)也可以,用bucket. 比较巧妙。 + + +``` +/* +Given an array of citations (each citation is a non-negative integer) of a researcher, +write a function to compute the researcher's h-index. + +According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers +have at least h citations each, +and the other N − h papers have no more than h citations each." + +For example, given citations = [3, 0, 6, 1, 5], which means the researcher has 5 papers in total and +each of them had received 3, 0, 6, 1, 5 citations respectively. +Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, his h-index is 3. + +Note: If there are several possible values for h, the maximum one is taken as the h-index. + +Hint: + +An easy approach is to sort the array first. +What are the possible values of h-index? +A faster approach is to use extra space. + +Google Facebook +Hide Tags Hash Table Sort +Hide Similar Problems (M) H-Index II + +*/ + +/* + Thoughts:O(nlogn) + N = 5, so max of h = 5. min of h = 0. + 1. h = 5, loop through the array and count the # of citations that are >= h. + 2 .h = 4 ... h=1, h=0. + => O(n^2). + + If sort it : 0,1,3,5,6 + Find find index x = N - h, and arr[x] >= h + that becomes find index x that arr[x] >=h ,where h = N - x. + Foor loop on h, O(n) + pick x = N - h, and check if arr[x] >= h + h = 5, x = 5 -5 = 0. arr[x] = 0 < h. not working + h = 4, x = 5 - 4 = 1. arr[x] = 1. no. + h=3,x=5-3 =2,arr[x]=3 3>=3, okay. + nLogn + N = O(nlogn) + + +*/ +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + Arrays.sort(citations); + for (int h = citations.length; h > 0; h--) { + int x = citations.length - h; + if (citations[x] >= h) { + return h; + } + } + return 0; + } +} + + +/* + Thoughts: as the hint shows, use extra space and make it faster. + citations = [3, 0, 6, 1, 5], + (http://buttercola.blogspot.com/2015/09/leetcode-h-index.html?_sm_au_=iHVFjb76ZHj7ND5D) + 1. For loop to count++ in correct buttkit regardless of the index. + If arr[x] <= n, then bucket[arr[x]]++. that means, the bucket with index of arr[x] should store this arr[x] element. + If arr[x] > n, well, that means it exceeds bucket.length (in this application, it means it's already greater than the max of h=n) + so let's just put it in bucket[n]++. + Obvisouly, we need bucket[n + 1] + 2. Each bucket slot now stores #of values that's >= it's index h, in ascending order ofcourse. + so we can do another for loop, to sum one by one, from h = n ~ 0, (because we need higest possible h) + if sum >= h, that is the rst. +*/ +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + int n = citations.length; + int[] bucket = new int[n + 1]; + //fill bucket + for (int i = 0; i < n; i++) { + int bucketSlot = citations[i]; + if (citations[i] <= n) { + bucket[bucketSlot]++; + } else {//bucketSlot > n + bucket[n]++; + } + } + + //Find best H + int sum = 0; + for (int h = n; h >= 0; h--) { + if (sum + bucket[h] >= h) { + return h; + } + sum += bucket[h]; + } + return 0; + } +} +``` \ No newline at end of file diff --git a/Java/Happy Number.java b/Java/Happy Number.java new file mode 100755 index 0000000..9e3ca95 --- /dev/null +++ b/Java/Happy Number.java @@ -0,0 +1,60 @@ +E + +Basic Implementation of the requirements. + +用HashSet存查看过的数值。若重复,return false. + +``` +/* +Write an algorithm to determine if a number is happy. + +A happy number is a number defined by the following process: +Starting with any positive integer, replace the number by the sum of the squares of its digits, +and repeat the process until the number equals 1 (where it will stay), +or it loops endlessly in a cycle which does not include 1. +Those numbers for which this process ends in 1 are happy numbers. + +Example +19 is a happy number + +1^2 + 9^2 = 82 +8^2 + 2^2 = 68 +6^2 + 8^2 = 100 +1^2 + 0^2 + 0^2 = 1 +Tags Expand +Hash Table Mathematics +*/ + +/* + Thoughts: + Try some examples then find out: if it's not happy number, the 'sum of square of its digits' will + repeatedly occur. Use hashset to track existance. +*/ +public class Solution { + public boolean isHappy(int n) { + if (n <= 0) { + return false; + } + long sum = n; + HashSet set = new HashSet(); + while (sum != 1) { + String s = String.valueOf(sum); + sum = 0; + for (char c : s.toCharArray()){ + sum += (c-'0')*(c-'0'); + } + if (set.contains(sum)) { + return false; + } else { + set.add(sum); + } + } + return true; + } +} + + + + + +``` \ No newline at end of file diff --git a/Java/Hash Function.java b/Java/Hash Function.java old mode 100644 new mode 100755 index ba32154..c068112 --- a/Java/Hash Function.java +++ b/Java/Hash Function.java @@ -1,3 +1,20 @@ +E + +解释Hash怎么道理。Hash function例子: +hashcode("abcd") = (ascii(a) * 33^3 + ascii(b) * 33^2 + ascii(c) *33^1 + ascii(d)*33^0) % HASH_SIZE + +用到的参数比如: magic number 33, HASH_SIZE. + +Hash的用法是:给一个string key, 转换成数字,从而把size变得更小。 +真实的implementation还要处理collision, 可能需要design hash function 等等。 + + +每一步都: +hashRst = hashRst * 33 + (int)(key[i]); +hashRst = hashRst % HASH_SIZE; +原因是,hashRst会变得太大,所以不能算完再%... + +``` /* In data structure Hash, hash function is used to convert a string(or any other type) into an integer smaller than hash size and bigger or equal to zero. The objective of @@ -8,7 +25,7 @@ In data structure Hash, hash function is used to convert a string(or any other t hashcode("abcd") = (ascii(a) * 33^3 + ascii(b) * 33^2 + ascii(c) *33^1 + ascii(d)*33^0) % HASH_SIZE - = (97* 333 + 98 * 332 + 99 * 33 +100) % HASH_SIZE + = (97* 33^3 + 98 * 33^2 + 99 * 33 +100) % HASH_SIZE = 3595978 % HASH_SIZE @@ -29,12 +46,15 @@ In data structure Hash, hash function is used to convert a string(or any other t Tags Expand Hash Table +*/ + +/* Thinking process: Use given hash function. However, need to consider integer overflow. A simple way: save it as a long during calculation. Then return a (int). -*/ +*/ class Solution { /** * @param key: A String you should hash @@ -54,3 +74,5 @@ public int hashCode(char[] key, int HASH_SIZE) { } }; + +``` \ No newline at end of file diff --git a/Java/HashHeap.java b/Java/HashHeap.java new file mode 100755 index 0000000..e3b6488 --- /dev/null +++ b/Java/HashHeap.java @@ -0,0 +1,179 @@ +H + +非题.是从九章找来的HashHeap implementation. + +``` +/** + * 本代码由九章算法编辑提供。没有版权欢迎转发。 + * - 九章算法致力于帮助更多中国人找到好的工作,教师团队均来自硅谷和国内的一线大公司在职工程师。 + * - 现有的面试培训课程包括:九章算法班,系统设计班,BAT国内班 + * - 更多详情请见官方网站:http://www.jiuzhang.com/ + */ + +class HashHeap { + ArrayList heap; + String mode; + int size_t; + HashMap hash; + + class Node { + public Integer id; + public Integer num; + + Node(Node now) { + id = now.id; + num = now.num; + } + + Node(Integer first, Integer second) { + + this.id = first; + this.num = second; + } + } + + public HashHeap(String mod) { // 传入min 表示最小堆,max 表示最大堆 + // TODO Auto-generated constructor stub + heap = new ArrayList(); + mode = mod; + hash = new HashMap(); + size_t = 0; + } + + int peak() { + return heap.get(0); + } + + int size() { + return size_t; + } + + Boolean empty() { + return (heap.size() == 0); + } + + int parent(int id) { + if (id == 0) { + return -1; + } + return (id - 1) / 2; + } + + int lson(int id) { + return id * 2 + 1; + } + + int rson(int id) { + return id * 2 + 2; + } + + boolean comparesmall(int a, int b) { + if (a <= b) { + if (mode == "min") + return true; + else + return false; + } else { + if (mode == "min") + return false; + else + return true; + } + + } + + void swap(int idA, int idB) { + int valA = heap.get(idA); + int valB = heap.get(idB); + + int numA = hash.get(valA).num; + int numB = hash.get(valB).num; + hash.put(valB, new Node(idA, numB)); + hash.put(valA, new Node(idB, numA)); + heap.set(idA, valB); + heap.set(idB, valA); + } + + Integer poll() { + size_t--; + Integer now = heap.get(0); + Node hashnow = hash.get(now); + if (hashnow.num == 1) { + swap(0, heap.size() - 1); + hash.remove(now); + heap.remove(heap.size() - 1); + if (heap.size() > 0) { + siftdown(0); + } + } else { + hash.put(now, new Node(0, hashnow.num - 1)); + } + return now; + } + + void add(int now) { + size_t++; + if (hash.containsKey(now)) { + Node hashnow = hash.get(now); + hash.put(now, new Node(hashnow.id, hashnow.num + 1)); + + } else { + heap.add(now); + hash.put(now, new Node(heap.size() - 1, 1)); + } + + siftup(heap.size() - 1); + } + + void delete(int now) { + size_t--; + ; + Node hashnow = hash.get(now); + int id = hashnow.id; + int num = hashnow.num; + if (hashnow.num == 1) { + + swap(id, heap.size() - 1); + hash.remove(now); + heap.remove(heap.size() - 1); + if (heap.size() > id) { + siftup(id); + siftdown(id); + } + } else { + hash.put(now, new Node(id, num - 1)); + } + } + + void siftup(int id) { + while (parent(id) > -1) { + int parentId = parent(id); + if (comparesmall(heap.get(parentId), heap.get(id)) == true) { + break; + } else { + swap(id, parentId); + } + id = parentId; + } + } + + void siftdown(int id) { + while (lson(id) < heap.size()) { + int leftId = lson(id); + int rightId = rson(id); + int son; + if (rightId >= heap.size() || (comparesmall(heap.get(leftId), heap.get(rightId)) == true)) { + son = leftId; + } else { + son = rightId; + } + if (comparesmall(heap.get(id), heap.get(son)) == true) { + break; + } else { + swap(id, son); + } + id = son; + } + } +} +``` \ No newline at end of file diff --git a/Java/HashWithArray.java b/Java/HashWithArray.java old mode 100644 new mode 100755 index 5b03fa9..46bb835 --- a/Java/HashWithArray.java +++ b/Java/HashWithArray.java @@ -1,3 +1,7 @@ +E + + +``` /* Self Test: Implement HashTable with just array and integer. @@ -62,8 +66,4 @@ public int get(int key) { - - - - - +``` \ No newline at end of file diff --git a/Java/HashWithCustomizedClass(LinkedList).java b/Java/HashWithCustomizedClass(LinkedList).java new file mode 100644 index 0000000..190525a --- /dev/null +++ b/Java/HashWithCustomizedClass(LinkedList).java @@ -0,0 +1,167 @@ +M + +练习HashMap with customized class. + +``` +/* +Build Hashtable datastructure with three methods: set, get, getrandom. + +Note1: getrandom needs to pick evenly/uniformaly distributed entry. + +Note2: to be realistic, hashtable should be able to handle collision, that's where linkedlist comes into play. + +Note3: use default object.hashcode() function to get hash code, then apply hashcode % table size + + +More about O(1) random access + If no collision, uniform random access is easy. + +With collision, need to figure our how to access element on the linkedlist with O(1), but it's unlikely. + So, like Java HashMap, we can implement rehashing. Bascially, when map size increase to over capacity, double the capacity. + +*/ + +import java.io.*; +import java.util.*; + +public class CHashMap { + public int capacity; + public int count; + public Entry[] table; + + public class Entry { + public V value; + public K key; + public Entry next; + + public Entry(K key, V value, Entry next) { + this.value = value; + this.key = key; + this.next = next; + } + } + + + public CHashMap() { + this.capacity = 16; + this.table = new Entry[this.capacity]; + this.count = 0; + } + + public CHashMap(int capacity) { + this.capacity = capacity; + this.table = new Entry[this.capacity]; + this.count = 0; + } + + public V get(K key) { + if (key == null) { + return null; + } + int hashedKey = hashFunction(key); + if (table[hashedKey] != null) { + Entry node = table[hashedKey]; + while (node != null) { + if (node.key.equals(key)) { + return node.value; + } + node = node.next; + } + } + return null; + } + + + public void put(K key, V value) { + if (key == null) { + return; + } + this.count++; + Entry entry = new Entry(key, value, null); + int hashedKey = hashFunction(key); + if (table[hashedKey] == null) { + table[hashedKey] = entry; + } else { + Entry node = table[hashedKey]; + if (node.key.equals(key)) { + table[hashedKey] = entry; + entry.next = node.next; + return; + } + while (node.next != null) { + if (node.next.key.equals(key)) { + Entry temp = node.next; + node.next = entry; + entry.next = temp.next; + return; + } + node = node.next; + } + node.next = entry; + } + } + + public int hashFunction (K key) { + return Math.abs(key.hashCode()) % this.capacity; + } + + public void display() { + for (int i = 0; i < table.length; i++) { + Entry node = table[i]; + StringBuffer sb = new StringBuffer(); + while (node != null) { + sb.append("[key: " + node.key + ", value: " + node.value + "], "); + node = node.next; + } + if (sb.length() != 0) + System.out.println(sb.toString()); + } + System.out.println(); + } + + /* + If no collision, uniform random access is easy. + + With collision, need to figure our how to access element on the linkedlist with O(1), but it's unlikely. + + */ + public V getRandom() { + Random rd = new Random(); + int hashedKey = hashFunction(rd.nextInt(this.capacity)); + return table[hashedKey]; + } + + + + + + + public static void main(String[] args) { + CHashMap map = new CHashMap(2); + + System.out.println("TEST SET------"); + map.put('a', "1st string"); + map.put('b', "2nd string!"); + map.display(); + map.put('a', "wowo change"); + map.display(); + + + System.out.println("TEST PUT------"); + System.out.println(map.get('a')); + System.out.println(map.get('c')); + map.put('c', "okay test c"); + System.out.println(map.get('c')); + map.display(); + + System.out.println("TEST COLLISION------"); + map.put('d', "test d"); + map.put('e', "test E"); + map.display(); + + + //test getrandom + + } +} +``` \ No newline at end of file diff --git a/Java/Heapify.java b/Java/Heapify.java old mode 100644 new mode 100755 index f4f17fe..1dc4c06 --- a/Java/Heapify.java +++ b/Java/Heapify.java @@ -1,13 +1,27 @@ +M + +Heap用的不多. 得用一下, 才好理解。 +通常default 的PriorityQueue就是给了一个现成的min-heap:所有后面的对应element都比curr element 小。 + Heapify里面的siftdown的部分: - 只能从for(i = n/2-1 ~ 0), 而不能从for(i = 0 ~ n/2 -1) - 这是不是因为siftdown每次只顺脚下的孩子,所以必须中间开花,向上跑的时候才能确保脚下是符合heap规则的 + 只能从for(i = n/2-1 ~ 0), 而不能从for(i = 0 ~ n/2 -1): 必须中间开花,向上跑的时候才能确保脚下是符合heap规则的 + +Heapify/SiftDown做了什么? +确保在heap datastructure里面curr node下面的两个孩子,以及下面所有的node都遵循一个规律。 +比如在这里,若是min-heap,就是后面的两孩子都要比自己大。若不是,就要swap。 + +还是要记一下min-heap的判断规律:for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. + +siftdown时:在curr node和两个son里面小的比较。如果的确curr < son, 搞定,break while. +但若curr 并不比son小,那么就要换位子,而且继续从son的位子往下面盘查。 ``` /* Given an integer array, heapify it into a min-heap array. -For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i]. -Have you met this question in a real interview? Yes +For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] +and A[i * 2 + 2] is the right child of A[i]. + Example Given [3,2,1,4,5], return [1,2,3,4,5] or any legal heap array. @@ -15,12 +29,15 @@ O(n) time complexity Clarification -What is heap? -Heap is a data structure, which usually have three methods: push, pop and top. where "push" add a new element the heap, "pop" delete the minimum/maximum element in the heap, "top" return the minimum/maximum element. +What is heap? +Heap is a data structure, which usually have three methods: push, pop and top. +where "push" add a new element the heap, "pop" delete the minimum/maximum element in the heap, +"top" return the minimum/maximum element. What is heapify? -Convert an unordered integer array into a heap array. If it is min-heap, for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. +Convert an unordered integer array into a heap array. +If it is min-heap, for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. What if there is a lot of solutions? Return any of them. @@ -31,7 +48,7 @@ /* Thoughts: -Based on the knowledge of Hash Heap: http://www.jiuzhang.com/solutions/hash-heap/ +Based on the knowledge of Hash Heap: http://www.jiuzhang.com/solutions/hashheap/ Try to implement part of the Heap basis, heapify. In this problem, re-organize the input array to fit heap basis @@ -58,10 +75,6 @@ If not, swap(curr,son) public class Solution { - /** - * @param A: Given an integer array - * @return: void - */ public void heapify(int[] A) { if (A == null || A.length == 0) { return; @@ -98,15 +111,4 @@ public void heapify(int[] A) { - - - - - - - - - - - ``` \ No newline at end of file diff --git a/Java/House Robber II.java b/Java/House Robber II.java new file mode 100644 index 0000000..8db2466 --- /dev/null +++ b/Java/House Robber II.java @@ -0,0 +1,82 @@ +M + +和House Robber I 类似, DP. + +根据dp[i-1]是否被rob来讨论dp[i]: dp[i] = Math.max(dp[i-1], dp[i - 2] + nums[i - 1]); + +特别的是,末尾的last house 和 first house相连。这里就需要分别讨论两种情况: +1. 最后一个房子被rob +2. 最后一个房子没被rob + +两种情况做完,综合对比一下. + +``` +/* +Note: This is an extension of House Robber. + +After robbing those houses on that street, the thief has found himself a new place for his thievery +so that he will not get too much attention. This time, all houses at this place are arranged in a circle. +That means the first house is the neighbor of the last one. +Meanwhile, the security system for these houses remain the same as for those in the previous street. + +Given a list of non-negative integers representing the amount of money of each house, +determine the maximum amount of money you can rob tonight without alerting the police. + +Credits: +Special thanks to @Freezen for adding this problem and creating all test cases. + +Subscribe to see which companies asked this question + + + Dynamic Programming +Hide Similar Problems (E) House Robber (M) Paint House (E) Paint Fence (M) House Robber III + + + +*/ + +/* + Each house depends on front and back houses + Two possible case for the last house: rob or not robbed. So we can do two for loop, then compare the + two differnet future. +*/ +public class Solution { + public int rob(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } else if (nums.length == 1) { + return nums[0]; + } else if (nums.length == 2) { + return Math.max(nums[0], nums[1]); + } + + int n = nums.length; + + //Last house not robbed + int[] dp1 = new int[n]; + dp1[0] = nums[0]; + dp1[1] = Math.max(nums[0], nums[1]); + for (int i = 2; i < n - 1; i++) { + dp1[i] = Math.max(dp1[i - 1], dp1[i - 2] + nums[i]); + } + dp1[n - 1] = dp1[n - 2]; + + //Last house robbed + int[] dp2 = new int[n]; + dp2[0] = 0; + dp2[1] = nums[1]; + for (int i = 2; i < n - 2; i++) { + dp2[i] = Math.max(dp2[i - 1], dp2[i - 2] + nums[i]); + } + dp2[n - 1] = dp2[n - 3] + nums[n - 1]; + + //Compare + return Math.max(dp2[n - 1], dp1[n - 1]); + } +} + + + + + +``` \ No newline at end of file diff --git a/Java/House Robber III.java b/Java/House Robber III.java new file mode 100644 index 0000000..373dde6 --- /dev/null +++ b/Java/House Robber III.java @@ -0,0 +1,105 @@ +H + +由于无法用简单的方法构造DP array, 所以采取了普通的DFS。 + +The catch: +判断当下的node是否被采用,用一个boolean来表示. + +1. 如果curr node被采用,那么下面的child一定不能被采用。 +2. 如果curr node不被采用,那么下面的children有可能被采用,但也可能略过,所以这里用Math.max() 比较一下两种可能有的dfs结果。 + + +``` +/* +The thief has found himself a new place for his thievery again. +There is only one entrance to this area, called the "root." +Besides the root, each house has one and only one parent house. +After a tour, the smart thief realized that "all houses in this place forms a binary tree". +It will automatically contact the police if two directly-linked houses were broken into on the same night. + +Determine the maximum amount of money the thief can rob tonight without alerting the police. + +Example 1: + 3 + / \ + 2 3 + \ \ + 3 1 +Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. + +Example 2: + 3 + / \ + 4 5 + / \ \ + 1 3 1 +Maximum amount of money the thief can rob = 4 + 5 = 9. +Credits: +Special thanks to @dietpepsi for adding this problem and creating all test cases. + +Subscribe to see which companies asked this question + + + Tree Depth-first Search +Hide Similar Problems (E) House Robber (M) House Robber II + + +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +/* + 3.24.2016 + Thought: dfs should be able to handle this. +*/ +public class Solution { + public int rob(TreeNode root) { + if (root == null) { + return 0; + } else if (root.left == null && root.right == null) { + return root.val; + } + return Math.max(dfs(root,true), dfs(root, false)); + } + + public int dfs (TreeNode node, boolean visit) { + if (node.left == null && node.right == null) { + if (visit){ + return node.val; + } else { + return 0; + } + } + int left = 0; + int right = 0; + if (visit) { + if (node.left != null) { + left = dfs(node.left, !visit); + } + if (node.right != null) { + right = dfs(node.right, !visit); + } + return node.val + left + right; + } else { + if (node.left != null) { + left = Math.max(dfs(node.left, !visit), dfs(node.left, visit)); + } + if (node.right != null) { + right = Math.max(dfs(node.right, !visit), dfs(node.right, visit)); + } + return left + right; + } + + } +} + + +``` \ No newline at end of file diff --git a/Java/House Robber.java b/Java/House Robber.java index e021fce..0b68009 100644 --- a/Java/House Robber.java +++ b/Java/House Robber.java @@ -1,7 +1,10 @@ -最基本的dp。 -看前一个或前两个的情况,再总和考虑当下的。 -思考的适合搞清楚当下的和之前的情况的关系。 -滚动数组的优化,就是确定了是这类“只和前一两个位子“相关的Fn而推出的。 +E + +最基本的dp。 +看前一个或前两个的情况,再总和考虑当下的。 +思考的适合搞清楚当下的和之前的情况的关系。 +滚动数组的优化,就是确定了是这类“只和前一两个位子“相关的Fn而推出的。 + ``` /* You are a professional robber planning to rob houses along a street. @@ -13,7 +16,7 @@ Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. -Have you met this question in a real interview? Yes + Example Given [3, 8, 4], return 8. @@ -24,12 +27,48 @@ Dynamic Programming */ + + + +/* + 3.24.2016 recap + Find max, either add nums[i - 1] or not. Use dp[i] to track the max money take from [0 ~ i] +*/ +public class Solution { + public int rob(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } else if (nums.length == 1) { + return nums[0]; + } + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (int i = 2; i < dp.length; i++) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + + return dp[dp.length - 1]; + } +} + +/* + Should be able to do with recursive way. + dfs(nums, index, robFlag, sum) + Based on robFlag (true/false), this recursive level will be limited weather we can pick the current + house or no. Update robFlag, sum, index and go into next level of dfs. +*/ + + + + /* Thoughts: dp[i]: the best we can rob by i. If I'm at house i, I'll either pick i or not pick i. Pick i: dp[i-2] + A[i] - Not pick i: dp[i+1] + Not pick i: dp[i-1] fn: dp[i] = Math.max(dp[i-1], dp[i-2] + A[i]) Init: @@ -96,9 +135,4 @@ public long houseRobber(int[] A) { - - - - - ``` \ No newline at end of file diff --git a/Java/Identical Binary Tree.java b/Java/Identical Binary Tree.java index 6aadd44..5b4e7b8 100644 --- a/Java/Identical Binary Tree.java +++ b/Java/Identical Binary Tree.java @@ -1,5 +1,9 @@ -Divide, && all. +E + +Divide, && 每种情况(左右一一对应) 注意 null states + + ``` /* Check if two binary trees are identical. Identical means the two binary trees have the same structure and every identical position has the same value. diff --git a/Java/Implement Stack by Two Queues.java b/Java/Implement Stack by Two Queues.java new file mode 100644 index 0000000..686b8c9 --- /dev/null +++ b/Java/Implement Stack by Two Queues.java @@ -0,0 +1,80 @@ +两个Queue,交互倒水 +用一个Temp做swap + +做法1: +逻辑在top()/pop()里, 每次换水,查看末尾项. + +做法2: +逻辑在push里面: +1. x 放q2。 +2. q1全部offer/append到q2. +3. 用一个Temp做swap q1, q2. +q1的头,就一直是最后加进去的值. +``` +/* +Implement Stack by Two Queues + +Implement a stack by two queues. The queue is first in first out (FIFO). +That means you can not directly pop the last element in a queue. + +Have you met this question in a real interview? Yes +Example +push(1) +pop() +push(2) +isEmpty() // return false +top() // return 2 +pop() +isEmpty() // return true +Tags Expand +Stack Queue + +*/ + +/* + Thoughts: + 2 queue are like two cups. We are fliping water into/out between q1 and q2. + pop and top are fliping water. + Use p1 as the base. +*/ + +class Stack { + private Queue q1 = new LinkedList(); + private Queue q2 = new LinkedList(); + // Push a new item into the stack + public void push(int x) { + q1.offer(x); + } + + // Pop the top of the stack + public void pop() { + while (q1.size() > 1) { + q2.offer(q1.poll()); + } + q1.poll(); + swap(); + } + + // Return the top of the stack + public int top() { + while (q1.size() > 1) { + q2.offer(q1.poll()); + } + int rst = q1.poll(); + q2.offer(rst); + swap(); + return rst; + } + + public void swap(){ + Queue temp = q1; + q1 = q2; + q2 = temp; + } + + // Check the stack is empty or not. + public boolean isEmpty() { + return q1.isEmpty(); + } +} +``` \ No newline at end of file diff --git a/Java/Implement Stack.java b/Java/Implement Stack.java new file mode 100644 index 0000000..7c4a3dd --- /dev/null +++ b/Java/Implement Stack.java @@ -0,0 +1,61 @@ +stack 后入先出. +Data Structure: ArrayList +return/remove ArrayList的末尾项。 + +``` +/* + Implement Stack + +Implement a stack. You can use any data structure inside a stack except stack itself to implement it. + + +Example +push(1) +pop() +push(2) +top() // return 2 +pop() +isEmpty() // return true +push(3) +isEmpty() // return false +Tags Expand +Array Stack +*/ + +/* +Thoughts: +use arraylist and a index tracker - leng +push: add to end +pop: remove end +top: get end. +isEmpty: return length +*/ + +class Stack { + private ArrayList list = new ArrayList(); + // Push a new item into the stack + public void push(int x) { + list.add(x); + } + + // Pop the top of the stack + public void pop() { + if (list.size() > 0) { + list.remove(list.size() - 1); + } + } + + // Return the top of the stack + public int top() { + if (list.size() > 0) { + return list.get(list.size() - 1); + } + return -1; + } + + // Check the stack is empty or not. + public boolean isEmpty() { + return list.size() == 0; + } +} +``` \ No newline at end of file diff --git a/Java/Implement Trie (Prefix Tree).java b/Java/Implement Trie (Prefix Tree).java new file mode 100644 index 0000000..9f0f47b --- /dev/null +++ b/Java/Implement Trie (Prefix Tree).java @@ -0,0 +1,111 @@ +Trie自己不多用到。 +如果是遇到一个一个字查询的题,可以考虑一下。 +构建TrieNode的时候要注意:如何找孩子?如果是个map的话,其实就挺好走位的。 +而且,每个node里面的 char 或者string有时候用处不大, +可以为空。但是有些题目,比如在结尾要return一些什么String,就可以在end string那边存一个真的String。 + + +``` +/* +Implement a trie with insert, search, and startsWith methods. + +Note: +You may assume that all inputs are consist of lowercase letters a-z. + +Tags: Trie Design +Similar Problems: (M) Add and Search Word - Data structure design + +*/ +/* +Thoughts: +Understand how prefix tree works, create TrieNode() smartly. (http://www.cnblogs.com/tonyluis/p/4563990.html) +Insert: whenever node does not exist, create a new node. +Search: search through each node, if any node not exist, false; at the end, that node has to be end of that path. +StartWith: very similar to search; at the end, as long as all nodes appear through the path, just return true. + +Note: +The contents of the TrieNode can be just a char, or it can be empty String except the end string: for that case +when we need return the end string. +Also, search and startWith is quite similar, remember that. +*/ + +class TrieNode { + char c; + boolean isEnd = false; + HashMap children = new HashMap(); + // Initialize your data structure here. + public TrieNode() { + } + public TrieNode(char c) { + this.c = c; + } +} + +public class Trie { + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + // Inserts a word into the trie. + public void insert(String word) { + TrieNode node = root; + HashMap children = node.children; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!children.containsKey(c)) { + TrieNode newNode = new TrieNode(c); + children.put(c, newNode); + } + node = children.get(c); + children = node.children; + if (i == word.length() - 1) { + node.isEnd = true; + } + } + } + + // Returns if the word is in the trie. + public boolean search(String word) { + TrieNode node = root; + HashMap children = node.children; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!children.containsKey(c)) { + return false; + } else { + node = children.get(c); + children = node.children; + } + if (i == word.length() - 1) { + return node.isEnd; + } + } + return false; + } + + // Returns if there is any word in the trie + // that starts with the given prefix. + public boolean startsWith(String prefix) { + TrieNode node = root; + HashMap children = node.children; + for (char c : prefix.toCharArray()) { + if (!children.containsKey(c)) { + return false; + } else { + node = children.get(c); + children = node.children; + } + } + return true; + } + + +} + +// Your Trie object will be instantiated and called as such: +// Trie trie = new Trie(); +// trie.insert("somestring"); +// trie.search("key"); +``` \ No newline at end of file diff --git a/Java/Implement Trie.java b/Java/Implement Trie.java old mode 100644 new mode 100755 index eab4dd0..9e7511d --- a/Java/Implement Trie.java +++ b/Java/Implement Trie.java @@ -1,5 +1,21 @@ -HashMap构建Trie。 -Trie用来insert word,找word, 找prefix +M + +Tire, 也即是 Prefix Tree. + +HashMap构建Trie。 Trie三个Method:  +1. Inset: 加 word +2. Search: 找word +3. StartWith: 找prefix + +只有两条children的是binary tree. 那么多个children就是Trie。 那么没有left/right pointer怎么找孩子? +用HashMap,以child的label为Key,value就是child node。 HashMap走位 + +Note: +node里的char在这是optional。 +另外有种题目,比如是跟其他种类的search相关,在结尾要return whole string,就可以在node里存一个up-to-this-point的String。 + + + ``` /* Implement a trie with insert, search, and startsWith methods. diff --git a/Java/Implement strStr().java b/Java/Implement strStr().java new file mode 100644 index 0000000..4d95a0b --- /dev/null +++ b/Java/Implement strStr().java @@ -0,0 +1,48 @@ +还挺多坑的. +1. border condition。 如果 haystack.length() < needle.length() 的话,必须错。但是这个可以优化省略。 +2. 当S2是“”的时候,也就是能在s1的其实位置找到s2....index = 0. +3. 记得如何在s1里面找s2. 就是把遍历s1的 i , 加上遍历s2的 j。 + +优化: +1. s1, s2长短可以不比较。因为forloop的时候: s1.length() - s2.length() + 1,如果s2长于s1,这里自然就断了。 +2. if(s1.charAT(i+j) == s2.charAT(j)). 可以省略。For loop 里面就Check到这个了。 +``` +/* +Implement strStr(). + +Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. + +Hide Company Tags Facebook +Hide Tags Two Pointers String +Hide Similar Problems (H) Shortest Palindrome + +*/ +public class Solution { + public int strStr(String haystack, String needle) { + if (needle == null || needle.length() == 0) { + return 0; + } + /* + else if (haystack == null || haystack.length() == 0 + || haystack.length() < needle.length()) { + return -1; + }*/ + int i = 0; + int j = 0; + + for (i = 0; i < haystack.length() - needle.length() + 1; i++) { + // if (haystack.charAt(i + j) == needle.charAt(j)) { + for (j = 0; j < needle.length(); j++) { + if (haystack.charAt(i + j) != needle.charAt(j)) { + break; + } + } + if (j == needle.length()) { + return i; + } + // } + } + return -1; + } +} +``` \ No newline at end of file diff --git a/Java/IndexMatch.java b/Java/IndexMatch.java new file mode 100755 index 0000000..12c73e2 --- /dev/null +++ b/Java/IndexMatch.java @@ -0,0 +1,54 @@ +E + +有序, 假设有这样的数字:target. +target 左边的数字,一定不比index大,target右边的数字,一定比index大。 +这样可以binary search.O(logn) + +``` +/* +来自网上uber面经:给一个有序数组(不含重复),返回任意一个数字,这个数字的值和它的数组下标相等 + +可能的follow up: +1. 如果含有重复数字怎么办? + 如果有序,也没问题,还是binary search + +2. 另一种follow up:找这样数字的边界. + 如果存在,那么和index match的一定在一块. + 找到任何一个candiate, 找边界,也可以binary search,只是match的condition不同罢了。 + +*/ +//Binary search. +import java.io.*; +import java.util.*; +class Solution { + + public int indexMatch(int[] nums) { + if (nums == null || nums.length == 0) { + return -1; + } + + int start = 0; + int end = nums.length - 1; + while (start + 1 < end) { + int mid = start + (end - start)/2; + if (nums[mid] == mid) { + return mid; + } else if (nums[mid] < mid) { + start = mid; + } else {//nums[mid] > mid + end = mid; + } + } + + return -1; + } + + public static void main(String[] args) { + System.out.println("START"); + int[] input = {-1, 0, 1, 3, 5, 8, 9};//return 3 + Solution sol = new Solution(); + int rst = sol.indexMatch(input); + System.out.println(rst); + } +} +``` \ No newline at end of file diff --git a/Java/Inorder Successor in Binary Search Tree.java b/Java/Inorder Successor in Binary Search Tree.java new file mode 100644 index 0000000..e6b0577 --- /dev/null +++ b/Java/Inorder Successor in Binary Search Tree.java @@ -0,0 +1,94 @@ +M + +画inorder图,发现规律.每个node的后继node(successor)有几种情况: +1. node.right 是个leaf到底了。那么就return. +2. set rightNode = node.right, 但发现rightNode has a lot left children to leaf. +3. 比如, node.right == null, 也就是node自己是leaf,要回头看山顶找Inorder traversal规则里的下一个。 + 发现:其实就是每层都把路过的curr node放在stack里,最上面的,就是当下改return的那个successor:) Done. + +``` +/* +Given a binary search tree (See Definition) and a node in it, find the in-order successor of that node in the BST. + +Have you met this question in a real interview? Yes +Example +Given tree = [2,1] and node = 1: + + 2 + / +1 +return node 2. + +Given tree = [2,1,3] and node = 2: + + 2 + / \ +1 3 +return node 3. + +Note +If the given node has no in-order successor in the tree, return null. + +Challenge +O(h), where h is the height of the BST. + +Tags Expand +Binary Search Tree Binary Tree +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +/* + Analysis the structure. + 1. Note1: When directing left, save curr in stack. Curr node will be re-visit with rules of in-order traversal. Write an example, will help refresh memory. + In the future, if node == target && node.right == null, then stack.pop() is the successor. + + 2. Note2: When p is found, and node.right != null. Be careful where: if node.right just ends there, surely return it, that's it; + However, if rightNode has left child, well, have to trace all the way down to left---end of the leaf + + Stack uses O(h) space +*/ + // + // +public class Solution { + Stack stack = new Stack(); + public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { + if (root == null || p == null) { + return null; + } + + if (root == p) { + if (root.right != null) { + //Hunt down rightNode's left leaf + TreeNode rightNode = root.right; + while (rightNode.left != null) { + rightNode = rightNode.left; + } + return rightNode; + } else if (!stack.isEmpty()) { + //Inorder pattern rules: + return stack.pop(); + } else { + return null; + } + } + + if (p.val < root.val && root.left != null) { + stack.push(root); + return inorderSuccessor(root.left, p); + } else if (p.val > root.val && root.right != null) { + return inorderSuccessor(root.right, p); + } + + return null; + } +} + +``` diff --git a/Java/Insert Interval.java b/Java/Insert Interval.java old mode 100644 new mode 100755 index 8498a3e..694de89 --- a/Java/Insert Interval.java +++ b/Java/Insert Interval.java @@ -1,9 +1,30 @@ +E + + +方法1:Scan Line +Interval 拆点,PriorityQueue排点。 +Merge时用count==0作判断点。 + +PriorityQueue: O(logN). 扫n点,总共:O(nLogn) + + +方法2: +O(n) 直接找到可以insert newInterval的位子. Insert。 这里已经给了sorted intervals by start point. 所以O(n) + +然后loop to merge entire interval array + +另外: 因为interval已经sort, 本想用Binary Search O(logn). 但是找到interval insert position, merge还是要用 O(n)。 +比如刚好newInterval cover entire list.... + + + +``` + /* Given a non-overlapping interval list which is sorted by start point. Insert a new interval into it, make sure the list is still in order and non-overlapping (merge intervals if necessary). -Have you met this question in a real interview? Yes Example Insert [2, 5] into [[1,2], [5,9]], we get [[1,9]]. @@ -12,14 +33,8 @@ Tags Expand Basic Implementation -Thoughts: -1. Find right position to insert: find the last start position that's <= newInterval.start -2. After insertion, merge. -3. How to merge? Look at merge inerval question */ - - /** * Definition of Interval: * public classs Interval { @@ -29,13 +44,92 @@ * this.end = end; * } */ + + + +/* +Thoughts: +What's the difference from merge intervals? +1. Create Class point (x, flag) +2. sort point in min-heap +3. when count increase and decreases to 0, that means we can close an interval +*/ + +public class Solution { + + class Point { + int x; + int flag; + public Point(int x, int flag) { + this.x = x; + this.flag = flag; + } + } + public List insert(List intervals, Interval newInterval) { + List rst = new ArrayList(); + if (intervals == null && newInterval == null) { + return rst; + } else if (intervals == null) { + rst.add(newInterval); + return rst; + } else if (newInterval == null) { + return intervals; + } + + PriorityQueue queue = new PriorityQueue(1, new Comparator(){ + public int compare(Point a, Point b){ + return a.x - b.x; + } + }); + + for (Interval range: intervals) { + queue.add(new Point(range.start, 1)); + queue.add(new Point(range.end, -1)); + } + + queue.add(new Point(newInterval.start, 1)); + queue.add(new Point(newInterval.end, -1)); + + int count = 0; + int startNew = 0; + int endNew = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + if (count == 0) { + startNew = p.x; + } + count += p.flag; + + while (!queue.isEmpty() && p.x == queue.peek().x) { + p = queue.poll(); + count += p.flag; + } + + if (count == 0) { + endNew = p.x; + Interval addInterval = new Interval(startNew, endNew); + rst.add(addInterval); + } + + }//end while + + return rst; + + } +} + + + +/* +O(n) +Thoughts: +1. Find right position to insert: find the last start position that's <= newInterval.start +2. After insertion, merge. +3. How to merge? Look at merge inerval question + + +*/ class Solution { - /** - * Insert newInterval into intervals. - * @param intervals: Sorted interval list. - * @param newInterval: A new interval. - * @return: A new sorted interval list. - */ public ArrayList insert(ArrayList intervals, Interval newInterval) { if (intervals == null || intervals.size() == 0 || newInterval == null) { if (newInterval != null) { @@ -72,4 +166,64 @@ public ArrayList insert(ArrayList intervals, Interval newInt return intervals; } -} \ No newline at end of file +} + + + + +/* + 2.26.2016 Not done. Looks like merging process still take O(n) + Can we do Binary Search for the index to insert newInterval.start, newInterval.end + find position x that has newInterval.start <= x.start + find position y that has y.end <= newInterval.end +*/ + + +class Solution { + public ArrayList insert(ArrayList intervals, Interval newInterval) { + ArrayList result = new ArrayList(); + + //Biary search for inStart, inEnd + int inStart = 0 + int inEnd = 0; + int start = 0; + int end = intervals.size(); + int mid; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (newInterval.start <= intervals.get(mid)) { + if (mid == 0 || intervals.get(mid).start == newInterval.start + || intervals.get(mid-1).start < newInterval.start) { + inStart = mid; + break; + } + end = mid; + } else { + start = mid; + } + } + start = 0; + end = intervals.size(); + while (start + 1 < end) { + mid = start + (end - start)/2; + if (newInterval.end <= intervals.get(mid)) { + if (mid == 0 || intervals.get(mid).start == newInterval.end + || intervals.get(mid-1).start < newInterval.end) { + inEnd = mid; + break; + } + end = mid; + } else { + start = mid; + } + } + + int diff = + + + return result; + } +} + + +``` \ No newline at end of file diff --git a/Java/Insert Node in a Binary Search Tree .java b/Java/Insert Node in a Binary Search Tree .java index d44d293..3ffc8f2 100644 --- a/Java/Insert Node in a Binary Search Tree .java +++ b/Java/Insert Node in a Binary Search Tree .java @@ -1,38 +1,64 @@ -/* -43% Accepted -Given a binary search tree and a new tree node, insert the node into the tree. You should keep the tree still be a valid binary search tree. - -Example -Given binary search tree as follow: +E - 2 +往Binary Search Tree里面加东西,一定会找到一个合适的leaf加上去。 - / \ +那么:就是说someNode.left or someNode.right是null时,就是insert node的地方。 -1 4 +找到那个someNode就按照正常的Binary Search Tree规律。 - / +``` - 3 - -after Insert node 6, the tree should be: +/* +Given a binary search tree and a new tree node, insert the node into the tree. +You should keep the tree still be a valid binary search tree. - 2 +Example +Given binary search tree as follow, after Insert node 6, the tree should be: - / \ + 2 2 + / \ / \ +1 4 --> 1 4 + / / \ + 3 3 6 +Challenge +Can you do it without recursion? -1 4 +Tags Expand +LintCode Copyright Binary Search Tree - / \ +*/ - 3 6 +//2.23.2016 recap +//Find node that has left or right==null. insert node on left/right +public class Solution { + public TreeNode insertNode(TreeNode root, TreeNode node) { + if (node == null || root == null) { + return node; + } + TreeNode dummy = root; + while (root != null) { + if (node.val < root.val) { + if (root.left == null) { + root.left = node; + break; + } + root = root.left; + } else if (node.val > root.val) { + if (root.right == null) { + root.right = node; + break; + } + root = root.right; + } + } + return dummy; + } +} -Challenge -Do it without recursion -Tags Expand -Binary Search Tree LintCode Copyright +/* +Previous solution Thinking process: Binary Search Tree: parent must < left node @@ -40,7 +66,6 @@ use a dummy node runNode to flow around on the binary search tree, compare with target node. Find the leaf node and add into appropriate pos. */ - public class Solution { /** * @param root: The root of the binary search tree. @@ -74,3 +99,5 @@ public TreeNode insertNode(TreeNode root, TreeNode node) { } } + +``` \ No newline at end of file diff --git a/Java/Integer to English Words.java b/Java/Integer to English Words.java new file mode 100644 index 0000000..c6f8e58 --- /dev/null +++ b/Java/Integer to English Words.java @@ -0,0 +1,90 @@ +/* +Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 2^31 - 1. + +For example, +123 -> "One Hundred Twenty Three" +12345 -> "Twelve Thousand Three Hundred Forty Five" +1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" +Hint: + +Did you see a pattern in dividing the number into chunk of words? For example, 123 and 123000. +Group the number by thousands (3 digits). You can write a helper function that takes a number less than 1000 and convert just that chunk to words. +There are many edge cases. What are some good test cases? Does your code work with input such as 0? Or 1000010? (middle chunk is zero and should not be printed out) +Tags: Math, String +Similar Problems: (M) Integer to Roman + +Thoughts: +2^31 - 1 = 2,147,483,647 +Trillion, Billion, Million, Thousand, Hundred, Ninty .... Ten, Nine ... One, Zero. + +1. Break the words to up to 4 parts: new break[4] by /(1000 ^ i) +2. For each i, deal with that 3-digit number in break[i] +3. Append corresponding words for each break[i] + +Special case: +zero +000 in one break[i]: skip the whole thing +*/ + + +public class Solution { + public String[] v1 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; + public String[] v2 = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; + public String numberToWords(int num) { + if (num < 0) { + return ""; + } + if (num == 0) { + return "Zero"; + } + String rst = ""; + for (int i = 0; i < 4; i++) { + int partial = num - (num / 1000) * 1000; + if (partial > 0) { + rst = helper(partial, i) + " " + rst; + } + num /= 1000; + } + while (rst.charAt(rst.length() - 1) == ' ') { + rst = rst.substring(0, rst.length() - 1); + } + return rst; + } + + public String helper(int num, int i) { + String str = ""; + if (num >= 100) { + int hund = num / 100; + str = v1[hund] + " Hundred "; + num = num % 100; + } + + if (num < 20) { + str += v1[num] + " "; + } else { + int numTens = num / 10; + int numDigit = num % 10; + str += v2[numTens] + " "; + str += v1[numDigit] + " "; + } + + while (str.charAt(str.length() - 1) == ' ') { + str = str.substring(0, str.length() - 1); + } + + //depending on i: + switch (i) { + case 1 : + str += " Thousand"; + break; + case 2 : + str += " Million"; + break; + case 3 : + str += " Billion"; + break; + } + + return str; + } +} \ No newline at end of file diff --git a/Java/Intersection of Two Linked Lists.java b/Java/Intersection of Two Linked Lists.java index 28078fa..7363445 100644 --- a/Java/Intersection of Two Linked Lists.java +++ b/Java/Intersection of Two Linked Lists.java @@ -1,5 +1,9 @@ +E + 长短list,找重合点。 -长度不同的话,切掉长的那个的extra length。 那么起点一样后,重合点就会同时到达。 +长度不同的话,切掉长的list那个的extra length。 那么起点一样后,重合点就会同时到达。 + + ``` /* Write a program to find the node at which the intersection of two singly linked lists begins. diff --git a/Java/Interval Minimum Number.java b/Java/Interval Minimum Number.java old mode 100644 new mode 100755 index 13b5047..6027902 --- a/Java/Interval Minimum Number.java +++ b/Java/Interval Minimum Number.java @@ -1,12 +1,16 @@ -又一个Segment tree的例子。 -把min number存在区间里面。 +M + +SegtmentTree, methods: Build, Query. 这题是在SegmentTreeNode里面存min. + +类似的有存:max, sum, min + -类似的有存:max, sum, min, count -如果考到的几率不高。那么这一系列题目就是练习写代码的能力,和举一反三的心态。 ``` /* -Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. Each query has two integers [start, end]. For each query, calculate the minimum number between index start and end in the given array, return the result list. +Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. +Each query has two integers [start, end]. For each query, calculate the minimum number between +index start and end in the given array, return the result list. Example For array [1,2,7,8,5], and queries [(1,2),(0,4),(2,4)], return [2,1,5] @@ -25,6 +29,7 @@ Given an integer array (index from 0 to n-1, where n is the size of this array), Thoughts: Build a SegmentMinTree. Do search using the interval + 如果考到的几率不高。那么这一系列题目就是练习写代码的能力,和举一反三的心态。 */ /** @@ -62,7 +67,7 @@ public SegmentMinTreeNode build(int start, int end, int[] A) { return node; } - + //Query method public int search(SegmentMinTreeNode root, int start, int end){ if (root.start == start && root.end == end) { return root.min; diff --git a/Java/Interval Sum II.java b/Java/Interval Sum II.java old mode 100644 new mode 100755 index 32e5a9d..31a1c2e --- a/Java/Interval Sum II.java +++ b/Java/Interval Sum II.java @@ -1,5 +1,7 @@ -这个题如果一上来就是做,拿的确烧脑,原因只有一个:太长了呀。就像Expression Tree一样。一旦知道了怎么做,就简单了,可如果生疏,也就难。 -这题是好几个SegmentTree的结合,但是没什么创新的。 +H + +SegmentTree大集合。记得几个Methods: Build, Query, Modify. 不难。只是要都记得不犯错:) + ``` /* Given an integer array in the construct method, implement two methods query(start, end) and modify(index, value): diff --git a/Java/Interval Sum.java b/Java/Interval Sum.java old mode 100644 new mode 100755 index 0e18dfe..73098df --- a/Java/Interval Sum.java +++ b/Java/Interval Sum.java @@ -1,11 +1,18 @@ -其实是segment tree 每个node上面加个sum。 -构建tree记得怎么弄就好了。很简单的。 -但是,我犯了错..在search的时候求mid时,忘记了以root为基准(我用interval.start and interval.end为基准,当然错了) -但实际上search起来就是binary search的想法,在interval/segment tree上面跑。顺顺哒。 +M + +其实是segment tree 每个node上面加个sum。 + +记得Segment Tree methods: Build, Query + +Note: 存在SegmentTreeNode里面的是sum. 其他题目可能是min,max ... or something else. + + ``` /* -Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. Each query has two integers [start, end]. For each query, calculate the sum number between index start and end in the given array, return the result list. +Given an integer array (index from 0 to n-1, where n is the size of this array), +and an query list. Each query has two integers [start, end]. +For each query, calculate the sum number between index start and end in the given array, return the result list. Example For array [1,2,7,8,5], and queries [(0,4),(1,2),(2,4)], return [23,9,20] @@ -87,18 +94,6 @@ public ArrayList intervalSum(int[] A, ArrayList queries) { for (Interval range : queries) { long sum = 0; - /* - //Check for errors, but don't have to do these checks - //Well, it's being checked in segment query II - if (range.start < root.start && range.end > root.end) { - sum = root.sum; - } else if (range.start < root.start && range.end <= root.end) { - sum = searchTree(root, root.start, range.end); - } else if (range.start >= root.start && range.end > root.end) { - sum = searchTree(root, range.start, root.end); - } else { - sum = searchTree(root, range.start, range.end); - }*/ sum = searchTree(root, range.start, range.end); rst.add(sum); } diff --git a/Java/Invert Binary Tree.java b/Java/Invert Binary Tree.java index 181aa0d..36b3769 100644 --- a/Java/Invert Binary Tree.java +++ b/Java/Invert Binary Tree.java @@ -1,3 +1,8 @@ +E + +non-recursive: BFS with queue。 或者regular recurisve - divide and conquer. + +``` /* Invert a binary tree. @@ -39,21 +44,21 @@ public class Solution { */ public void invertBinaryTree(TreeNode root) { if (root == null) { - return; + return; } Queue queue = new LinkedList(); queue.offer(root); while(!queue.isEmpty()) { - TreeNode node = queue.poll(); - TreeNode temp = node.left; - node.left = node.right; - node.right = temp; - if (node.left != null) { - queue.offer(node.left); - } - if (node.right != null) { - queue.offer(node.right); - } + TreeNode node = queue.poll(); + TreeNode temp = node.left; + node.left = node.right; + node.right = temp; + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } } } } @@ -67,16 +72,18 @@ public class Solution { */ public void invertBinaryTree(TreeNode root) { if (root == null) { - return; + return; } - TreeNode temp = root.left; - root.left = root.right; - root.right = temp; + TreeNode temp = root.left; + root.left = root.right; + root.right = temp; - invertBinaryTree(root.left); - invertBinaryTree(root.right); + invertBinaryTree(root.left); + invertBinaryTree(root.right); } } + +``` \ No newline at end of file diff --git a/Java/Isomorphic Strings.java b/Java/Isomorphic Strings.java new file mode 100644 index 0000000..619c6fa --- /dev/null +++ b/Java/Isomorphic Strings.java @@ -0,0 +1,62 @@ +E + +HashMap 来确认match。有几种情况考虑: + +1. Match. 就是map.containsKey, map.containsValue, and char1 == char2. Perfect. + +2. Either Key not exist, or Value not exit. False; + +3. Both key and Value exist, but map.get(char1) != char2. Miss-match. False. + +4. None of Key or Value exist in HashMap. Then add the match. + +``` +/* +Given two strings s and t, determine if they are isomorphic. + +Two strings are isomorphic if the characters in s can be replaced to get t. + +All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself. + +For example, +Given "egg", "add", return true. + +Given "foo", "bar", return false. + +Given "paper", "title", return true. + +Note: +You may assume both s and t have the same length. + +Hide Company Tags LinkedIn +Hide Tags Hash Table +Hide Similar Problems (E) Word Pattern + +*/ + + +//Use hashMap to store matches. If conflict, return false +public class Solution { + public boolean isIsomorphic(String s, String t) { + if (s == null || t == null) { + return false; + } else if (s.equals(t)) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + char charS = s.charAt(i); + char charT = t.charAt(i); + + if (!map.containsKey(charS) && !map.containsValue(charT)) { + map.put(charS, charT); + } else if (!map.containsKey(charS) || !map.containsValue(charT)) { + return false; + } else if (map.containsKey(charS) && map.containsValue(charT) && map.get(charS) != charT) { + return false; + } + } + return true; + } +} +``` diff --git a/Java/Jump Game II.java b/Java/Jump Game II.java index 26720f0..8f1afba 100644 --- a/Java/Jump Game II.java +++ b/Java/Jump Game II.java @@ -1,5 +1,22 @@ +H + +Greedy, 图解 http://www.cnblogs.com/lichen782/p/leetcode_Jump_Game_II.html + +维护一个range, 是最远我们能走的. + +index/i 是一步一步往前, 每次当 i <= range, 做一个while loop, 在其中找最远能到的地方 maxRange + +然后更新 range = maxRange + +其中step也是跟index是一样, 一步一步走. + +最后check的condition是,我们最远你能走的range >= nums.length - 1, 说明以最少的Step就到达了重点。Good. + + +``` /* -Given an array of non-negative integers, you are initially positioned at the first index of the array. +Given an array of non-negative integers, +you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. @@ -8,11 +25,51 @@ Example Given array A = [2,3,1,1,4] -The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.) +The minimum number of jumps to reach the last index is 2. +(Jump 1 step from index 0 to 1, then 3 steps to the last index.) Tags Expand Greedy Array +*/ + +/* + 3.18 recap. + Wihtin farest we can go, renew farest we can go, renew number of steps. + http://blog.csdn.net/havenoidea/article/details/11853301 + + 图解: + http://www.cnblogs.com/lichen782/p/leetcode_Jump_Game_II.html +*/ +//Greedy. Within max range we can jump to, do another loop to renew the max we can go. +public class Solution { + public int jump(int[] nums) { + if (nums == null || nums.length <= 1) { + return 0; + } + int index = 0; + int step = 0; + int range = 0; + int maxRange = 0; + + while (index < nums.length) { + if (range >= nums.length - 1) { + break; + } + while (index <= range) { + maxRange = Math.max(maxRange, index + nums[index]); + index++; + } + range = maxRange; + step++; + } + return step; + } +} + + +/* + Thanks to Yu’s Garden blog Thinking process: 0. Use two pointers pStart and pEnd to track the potential locations we can move to. @@ -20,7 +77,6 @@ If no max can read the tail of array, that means we need to move on. At this point, let pStart = pEnd + 1. At same time, move pEnd to the max spot we can go to. Since pEnd moves forward, we could step++ If max reach the tail of array, return the steps. */ - public class Solution { /** * @param A: A list of lists of integers @@ -55,3 +111,5 @@ public int jump(int[] A) { //Also DP from nineChapter: http://www.ninechapter.com/solutions/jump-game-ii/ + +``` \ No newline at end of file diff --git a/Java/Jump Game.java b/Java/Jump Game.java index 53664b9..07c265c 100644 --- a/Java/Jump Game.java +++ b/Java/Jump Game.java @@ -1,3 +1,16 @@ +M + +给出步数,看能不能reach to end. + +Status: +DP[i]: 在i点记录,i点之前的步数是否可以走到i点? True of false. + 其实j in [0~i)中间只需要一个能到达i 就好了 +Function: +DP[i] = DP[j] && (j + A[j]), for all j in [0 ~ i) +Return: + DP[dp.length - 1]; + +``` /* Given an array of non-negative integers, you are initially positioned at the first index of the array. @@ -31,12 +44,12 @@ public boolean canJump(int[] A) { if (A == null || A.length == 0) { return false; } - //By default, boolean[] can is all false + //By default, boolean[] can is all false boolean[] can = new boolean[A.length]; can[0] = true; for (int i = 1; i < A.length; i++) { for (int j = 0; j < i; j++) { - if (A[j] && (j + A[j] >= i)) { + if (can[j] && (j + A[j] >= i)) { can[i] = true; break; } @@ -80,3 +93,5 @@ public boolean canJump(int[] A) { } } + +``` \ No newline at end of file diff --git a/Java/Kth Largest Element.java b/Java/Kth Largest Element.java index 42bf011..d7f3d43 100644 --- a/Java/Kth Largest Element.java +++ b/Java/Kth Largest Element.java @@ -1,10 +1,27 @@ +M + +用Quick Sort 里面partion的一部分。 +partion的结果是那个low, 去找 low==nums.size() - k, 也就是倒数第K个。 +没找到继续partion recursively. + +sort的过程是排一个从小到大的list. (同样的代码还可以好xth smallest,mid变成x就好) + +Quick Sort: +每个iteration, 找一个pivot,然后从low,和high都和pivot作比较。 +找到一个low>pivot, high nums, int start, int end, int mid) { - - - - - - - - - - - - - - - - - - - - - - - +``` \ No newline at end of file diff --git a/Java/Kth Smallest Element in a BST.java b/Java/Kth Smallest Element in a BST.java new file mode 100644 index 0000000..2b70b2a --- /dev/null +++ b/Java/Kth Smallest Element in a BST.java @@ -0,0 +1,127 @@ +很容想到Inorder-binary-search-tree Traversal +Recursive 不难,然后稍微优化一下,确保rst.size() == k 时候,就可以return了。 +Iterative 稍微难想点:先把最左边的add, pop() stack, 加上右边(如果存在); 下一个轮回,如果又左孩子,又是一顿加。 + +``` +/* +Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. + +Note: +You may assume k is always valid, 1 ≤ k ≤ BST's total elements. + +Follow up: +What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? + +Hint: + +Try to utilize the property of a BST. +What if you could modify the BST node's structure? +The optimal runtime complexity is O(height of BST). +Credits: +Special thanks to @ts for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Tree Binary Search +Hide Similar Problems (M) Binary Tree Inorder Traversal + +*/ + +/* + + Based on binary seach tree, just do a in-order-traversal. + Store in rst. +*/ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + + +/* + //Iterative + + Add all left. + pop top (which will be left-most node) + set node = node.right; + if right != null, add to stack. Will trigger the left-adding-while-loop + if right == null, now node = null. Will not trigger the left-adding-whilte-loop +*/ +public class Solution { + public int kthSmallest(TreeNode root, int k) { + if (root == null || k <= 0) { + return -1; + } + + Stack stack = new Stack(); + stack.push(root); + TreeNode node = root; + while(!stack.isEmpty()) { + //Left first + while (node != null && node.left != null) { + stack.add(node.left); + node = node.left; + } + //Process left/curr + node = stack.pop(); + k--; + if (k == 0) { + return node.val; + } + node = node.right; + if (node != null) { + stack.push(node); + } + } + + return -1; + } + +} + + + +// Recursive +public class Solution { + public int kthSmallest(TreeNode root, int k) { + if (root == null || k <= 0) { + return -1; + } + + ArrayList rst = new ArrayList(); + helper(rst, root, k); + + if (rst.size() < k) { + return -1; + } + return rst.get(k - 1).val; + } + + + public void helper(ArrayList rst, TreeNode node, int k) { + if (rst.size() == k) { + return; + } + if (node.left == null && node.right == null) { + rst.add(node); + return; + } + + if (node.left != null) { + helper(rst, node.left, k); + } + rst.add(node); + if (node.right != null) { + helper(rst, node.right, k); + } + } +} + + + + +``` \ No newline at end of file diff --git a/Java/Kth Smallest Number in Sorted Matrix.java b/Java/Kth Smallest Number in Sorted Matrix.java new file mode 100644 index 0000000..c344a5a --- /dev/null +++ b/Java/Kth Smallest Number in Sorted Matrix.java @@ -0,0 +1,78 @@ +M + +和Merge K sorted Array/ List 类似:使用PriorityQueue。 + +因为Array的element无法直接找到next,所以用一个class Node 存value, x,y positions. + +/* +Find the kth smallest number in at row and column sorted matrix. + +Have you met this question in a real interview? Yes +Example +Given k = 4 and a matrix: + +[ + [1 ,5 ,7], + [3 ,7 ,8], + [4 ,8 ,9], +] +return 5 + +Challenge +O(k log n), n is the maximal number in width and height. + +Tags Expand +Heap Priority Queue Matrix + +*/ + + + +//PriorityQueue store front node. (Class Node), then output the kth in queue. +public class Solution { + class Node { + int val; + int x,y; + public Node(int val, int x, int y){ + this.val = val; + this.x = x; + this.y = y; + } + } + public int kthSmallest(int[][] matrix, int k) { + if (matrix == null || matrix[0] == null || matrix.length == 0 + || matrix[0].length == 0 || k <= 0) { + return -1; + } + + //Init queue + PriorityQueue queue = new PriorityQueue(k, + new Comparator(){ + public int compare(Node a, Node b) { + return a.val - b.val; + } + }); + + for (int i = 0; i < matrix.length; i++) { + if (matrix[i].length > 0) { + queue.offer(new Node(matrix[i][0], i, 0)); + } + } + + //Find kth + while (!queue.isEmpty()) { + Node node = queue.poll(); + if(k == 1) { + return node.val; + } + int x = node.x; + int y = node.y; + if (y < matrix[x].length - 1) { + queue.offer(new Node(matrix[x][y+1], x, y+1)); + } + k--; + } + + return -1; + } +} diff --git a/Java/Kth Smallest Sum In Two Sorted Arrays.java b/Java/Kth Smallest Sum In Two Sorted Arrays.java old mode 100644 new mode 100755 index 1f14c84..650f0ff --- a/Java/Kth Smallest Sum In Two Sorted Arrays.java +++ b/Java/Kth Smallest Sum In Two Sorted Arrays.java @@ -1,15 +1,19 @@ -挺勇猛. 还好网上有个题目是找kth最大。 -用priority queue. 每次把最小的展开,移位。分别x+1,或者y+1。 -因为当下的Min里面x,y都是最小的。所以下一个最小的不是(x+1,y),就是(x,y+1)。当然,放在PriorityQueue里面的原因就是,很可能跟之前在queue里面的pair产生比较。 -每次就poll()一个,放新candidate进去就好了。 -注意,这样的做法会用重复,比如例子(7,4)会出现两次。用一个HashSet挡一下。 +H + -学会用priorityqueue. +用priority queue. 每次把最小的展开,移位。分别x+1,或者y+1: +因为当下的Min里面x,y都是最小的。所以下一个最小的不是(x+1,y),就是(x,y+1)。 + +每次就poll()一个,放2个新candidate进去就好了。 +注意,这样的做法会用重复,比如例子(7,4)会出现两次。用一个HashSet挡一下。 注意,HashSet的唯一性,用一个"x,y"的string就可以代为解决。 + ``` /* -Given two integer arrays sorted in ascending order and an integer k. Define sum = a + b, where a is an element from the first array and b is an element from the second one. Find the kth smallest sum out of all possible sums. +Given two integer arrays sorted in ascending order and an integer k. Define sum = a + b, +where a is an element from the first array and b is an element from the second one. +Find the kth smallest sum out of all possible sums. Example Given [1, 7, 11] and [2, 4, 6]. diff --git a/Java/LRU Cache.java b/Java/LRU Cache.java new file mode 100755 index 0000000..74343e8 --- /dev/null +++ b/Java/LRU Cache.java @@ -0,0 +1,219 @@ +H + + +timeout method, 天真的来了一个O(n) 的解法,结果果然timeout. +一个map存数值。一个queue来存排位。 +每次有更新,就把最新的放在末尾;每次超过capaticity,就把大头干掉。很简单嘛,但是跑起来太久,失败了。 + +于是就来了第二个做法。其实还是跟方法一是类似的。 +用了一个特别的双向的LinkNode,有了head和tail,这样就大大加快了速度。 +主要加快的就是那个‘更新排位’的过程,过去我是O(n),现在O(1)就好了。 + +巧妙点: +1. head和tail特别巧妙:除掉头和尾,和加上头和尾,就都特别快。 +2. 用双向的pointer: pre和next, 当需要除掉任何一个node的时候,只要知道要除掉哪一个, +直接把node.pre和node.next耐心连起来就好了,node就自然而然的断开不要了。 + +一旦知道怎么解决了,就不是很特别,并不是难写的算法: +moveToHead() +insertHead() +remove() + +``` +/* +Design and implement a data structure for Least Recently Used (LRU) cache. +It should support the following operations: get and set. + +get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. +set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. + +Tags: Design + +*/ +/* +It looks like we need to do some design, according to (http://www.cnblogs.com/yuzhangcmu/p/4113462.html). Though, the solution's concept is quite similar as attempt1. + +1. The design uses HashMap, and 2-way LinkedList. Map +2. Use two dummy node: head and tail. When add/remove nodes, we are add/remove nodes in between head and tail. + So. head.next is our real 1st element + andd tail.pre is our real last element + +Note: +Be careful: when removing a node due to capacity issue, remember to remove both 1st node(head.next) and the corresponding entry in the map: map.remove(head.next.key) +*/ + +//Use double linked list to store value. +//Store key in hashmap to find node easily +//Functions: insert in front, remove node, +public class LRUCache { + class DoubleLinkedListNode { + int key, val; + DoubleLinkedListNode next,prev; + public DoubleLinkedListNode(int key, int val){ + this.key = key; + this.val = val; + next = null; + prev = null; + } + } + public int capacity; + public HashMap map; + public DoubleLinkedListNode head, tail; + public LRUCache(int capacity) { + this.capacity = capacity; + this.map = new HashMap(); + this.head = new DoubleLinkedListNode(-1, -1); + this.tail = new DoubleLinkedListNode(-1, -1); + head.next = tail; + head.prev = tail; + tail.next = head; + tail.prev = head; + } + + public int get(int key) { + if (map.containsKey(key)) { + DoubleLinkedListNode node = map.get(key); + moveToHead(node); + return node.val; + } else { + return -1; + } + } + + public void set(int key, int value) { + if (map.containsKey(key)) { + map.get(key).val = value; + moveToHead(map.get(key)); + } else { + DoubleLinkedListNode node = new DoubleLinkedListNode(key, value); + if (map.size() >= this.capacity) { + DoubleLinkedListNode rm = tail.prev; + remove(rm); + map.remove(rm.key); + } + insertHead(node); + map.put(key, node); + } + } + + public void moveToHead(DoubleLinkedListNode node) { + remove(node); + insertHead(node); + } + + //Helper functions + public void insertHead(DoubleLinkedListNode node) { + DoubleLinkedListNode next = head.next; + head.next = node; + node.prev = head; + node.next = next; + next.prev = node; + } + + public void remove(DoubleLinkedListNode node) { + DoubleLinkedListNode front = node.prev; + DoubleLinkedListNode end = node.next; + front.next = end; + end.prev = front; + } +} +/* +First Attempt: time exceeds + +Thoughts: +Easy to implement: cache the least-added item. However, we are looking for the cache of 'leaset-recently-used item'. + +'used' means the get() method: +whenever get, remove that key from the queue, and move that key to top. + +Time Cost: O(n) on get(), set() + + +*/ + +public class LRUCache { + private int cap; + private HashMap map; + private LinkedList queue; + public LRUCache(int capacity) { + this.cap = capacity; + this.map = new HashMap(); + this.queue = new LinkedList(); + } + + public int get(int key) { + if (map.containsKey(key)) { + moveUsedToTop(key); + return map.get(key); + } else { + return -1; + } + } + + public void set(int key, int value) { + if (map.containsKey(key)) { + moveUsedToTop(key); + map.put(key, value); + } else { + if (queue.size() >= cap) { + map.remove(queue.poll()); + } + queue.offer(key); + map.put(key, value); + } + + } + //O(n) + public void moveUsedToTop(int key) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i) == key) { + queue.remove(i); + queue.offer(key); + break; + } + } + } +} + +//O(n) timeout +//Get: find target in arraylist, remove it, insert in front, return map.get(target) +//Set: if exist, find in arraylist, remove it, insert in front. +// if not exist: check capacity: if full, remove last element and remove it from map. Then, insert in front, and insert into map. +public class LRUCache { + public ArrayList list = new ArrayList(); + public HashMap map = new HashMap(); + public int capacity; + public LRUCache(int capacity) { + this.capacity = capacity; + } + + public int get(int key) { + if (map.containsKey(key)) { + int ind = list.indexOf(key); + list.remove(ind); + list.add(0, key); + return map.get(key); + } + return -1; + } + + public void set(int key, int value) { + if (map.containsKey(key)) { + int ind = list.indexOf(key); + list.remove(ind); + list.add(0, key); + map.put(key, value); + } else { + list.add(0, key); + map.put(key, value); + if (list.size() > capacity) { + int rm = list.get(list.size() - 1); + list.remove(list.size() - 1); + map.remove(rm); + } + } + + } +} + +``` \ No newline at end of file diff --git a/Java/Letter Combinations of a Phone Number.java b/Java/Letter Combinations of a Phone Number.java index bbda83e..9ada873 100644 --- a/Java/Letter Combinations of a Phone Number.java +++ b/Java/Letter Combinations of a Phone Number.java @@ -1,3 +1,10 @@ +M + +方法1: Iterative with BFS using queue. + +方法2: Recursively adding chars per digit + +``` /* Given a digit string, return all possible letter combinations that the number could represent. @@ -17,19 +24,67 @@ A mapping of digit to letters (just like on the telephone buttons) is given belo String Backtracking Recursion Facebook Uber */ +/*3.7.2016 recap. Iterative way using BFS*/ +//Hashmap the list of chars. +//Use queue to append all possibile candidates. BFS +public class Solution { + public List letterCombinations(String digits) { + List rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + //Init map + HashMap map = new HashMap(); + map.put('2',"abc"); + map.put('3',"def"); + map.put('4',"ghi"); + map.put('5',"jkl"); + map.put('6',"mno"); + map.put('7',"pqrs"); + map.put('8',"tuv"); + map.put('9',"wxyz"); + // Init 1 digits and the chars in queue + Queue queue = new LinkedList(); + char c = digits.charAt(0); + String s = map.get(c); + for (int i = 0; i < s.length(); i++) { + queue.offer(s.charAt(i) + ""); + } + + int size = 0; + for (int i = 1; i < digits.length(); i++) {//iteratve all numbers + c = digits.charAt(i); + s = map.get(c); + size = queue.size(); + for (int j = 0; j < size; j++) {//iteratve old queue + String str = queue.poll(); + for (int k = 0; k < s.length(); k++) {//iteratve possibile chars per number key + queue.offer(str + s.charAt(k)); + } + } + } + while (!queue.isEmpty()) { + rst.add(queue.poll()); + } + + return rst; + } +} + + /* - Thoughts: have done this on Leetcode. - map integer to letters - combination of existing letters (by pressing fist number) with next number's letters. - put combinations into queue, reuse the queue. - finally, output into arraylist - - NON-recursive/iterative: use a queue. (Done this one Leetcode) - - This time, use recursive: - pass along rst, list, level number, digits, - for (combine list with all next level's candidates, map) - when level number == digits.length(), return the candidate into rst. + Thoughts: have done this on Leetcode. + map integer to letters + combination of existing letters (by pressing fist number) with next number's letters. + put combinations into queue, reuse the queue. + finally, output into arraylist + + NON-recursive/iterative: use a queue. (Done this one Leetcode) + + This time, use recursive: + pass along rst, list, level number, digits, + for (combine list with all next level's candidates, map) + when level number == digits.length(), return the candidate into rst. */ public class Solution { /** @@ -60,25 +115,25 @@ public ArrayList letterCombinations(String digits) { } public void helper(ArrayList rst, ArrayList list, - ArrayList map, String digits, int level){ - //If level is finished, compress into string - if (level == digits.length()) { - StringBuffer sb = new StringBuffer(); - for (String s : list) { - sb.append(s); - } - rst.add(sb.toString()); - return; - } - //For a specific list of candidates, face the level of chars - int num = Integer.parseInt(digits.substring(level, level + 1)); - String[] strs = map.get(num); - - for (int i = 0; i < strs.length; i++) { - list.add(strs[i]); - helper(rst, list, map, digits, level + 1); - list.remove(list.size() - 1); - } + ArrayList map, String digits, int level){ + //If level is finished, compress into string + if (level == digits.length()) { + StringBuffer sb = new StringBuffer(); + for (String s : list) { + sb.append(s); + } + rst.add(sb.toString()); + return; + } + //For a specific list of candidates, face the level of chars + int num = Integer.parseInt(digits.substring(level, level + 1)); + String[] strs = map.get(num); + + for (int i = 0; i < strs.length; i++) { + list.add(strs[i]); + helper(rst, list, map, digits, level + 1); + list.remove(list.size() - 1); + } } } @@ -148,3 +203,5 @@ public List letterCombinations(String digits) { + +``` \ No newline at end of file diff --git a/Java/Longest Common Prefix.java b/Java/Longest Common Prefix.java index c029d70..136a9c6 100644 --- a/Java/Longest Common Prefix.java +++ b/Java/Longest Common Prefix.java @@ -1,3 +1,10 @@ +M + +Nested loop, 每一次比较所有string 同位是否相等。 + +相等,append string. 不等,return. + +``` /* Given k strings, find the longest common prefix (LCP). @@ -9,33 +16,31 @@ Given k strings, find the longest common prefix (LCP). Tags Expand Enumeration Basic Implementation String LintCode Copyright +*/ + +/* + Thoughts: 1. Continuous while loop until something breaks out. 2. Str to record the longest prefix 3. for loop on each while-loop, based on strs[0] - Check if index exist - check if all other strs have same char at this point. If so, add it. If not, break. + Check if index exist + check if all other strs have same char at this point. If so, add it. If not, break. Note: Arrays: use strs.length -String: use str.length(). -Odd, right? I know ... dislike. -String seems to be supirior, it's a god damn object, and we have a method for checking string length. -For array, well, looks like it's been mistreated ... we are only reading a length property of the array object. +String: use str.length(). Note2: Ask for border case: when only 1 string, longest prefix turns out it's the strs[0] itself. + */ public class Solution { - /** - * @param strs: A list of strings - * @return: The longest common prefix - */ public String longestCommonPrefix(String[] strs) { if (strs == null || strs.length == 0) { - return ""; + return ""; } if (strs.length == 1) { return strs[0]; @@ -43,23 +48,26 @@ public String longestCommonPrefix(String[] strs) { String prefix = ""; int ind = 0; while (ind < strs[0].length()) { - char c = strs[0].charAt(ind); - boolean valid = false; - for (int i = 1; i < strs.length; i++) { - if (strs[i].length() > ind && strs[i].charAt(ind) == c) { - valid = true; - } else { - valid = false; - break; - } - } - if (valid) { - prefix += "" + c; - } else { - break; - } - ind++; + char c = strs[0].charAt(ind); + boolean valid = false; + for (int i = 1; i < strs.length; i++) { + if (strs[i].length() > ind && strs[i].charAt(ind) == c) { + valid = true; + } else { + valid = false; + break; + } + } + if (valid) { + prefix += "" + c; + } else { + break; + } + ind++; }//END WHILE return prefix; } -} \ No newline at end of file +} + + +``` \ No newline at end of file diff --git a/Java/Longest Palindromic Substring.java b/Java/Longest Palindromic Substring.java index 9093384..a9f98f1 100644 --- a/Java/Longest Palindromic Substring.java +++ b/Java/Longest Palindromic Substring.java @@ -1,3 +1,12 @@ +M + +方法1: 从中间劈开. 遍历i,从n个不同的点劈开:每次劈开都看是否可以从劈开出作为palindromic的中点延伸。 + Worst case: 整个string都是相同字符,time complexity变成: 1 + 2 +3 + ... +n = O(n^2) + +方法2: 穷举double for loop. O(n^2) + + +``` /* Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. @@ -7,14 +16,55 @@ Challenge O(n2) time is acceptable. Can you do it in O(n) time. -Tags Expand -String +Hide Company Tags Amazon Microsoft Bloomberg +Hide Tags String +Hide Similar Problems (H) Shortest Palindrome (E) Palindrome Permutation + + */ + /* O(n) way, not done yet */ +/* + 02.16.2016 recap: Worst case still O(n^2) + Find index i to split S into left and right. Check if from i's two sides can form a palindrom. + If so, mark the longest, then keep increasing i. +*/ +public class Solution { + public String longestPalindrome(String s) { + if (s == null || s.length() <= 1) { + return s; + } + String rst = ""; + for (int i = 0; i < s.length(); i++) { + if (i - 1 >= 0 && s.charAt(i - 1) == s.charAt(i)) { + rst = checkPalindrom(s, i-1, i, rst); + } + if (i + 1 < s.length() && s.charAt(i) == s.charAt(i + 1)) { + rst = checkPalindrom(s, i, i+1, rst); + } + if (i - 1 >= 0 && i + 1 < s.length() && s.charAt(i - 1) == s.charAt(i + 1)) { + rst = checkPalindrom(s, i-1, i+1, rst); + } + } + return rst; + } + + public String checkPalindrom(String s, int start, int end, String rst) { + while (start - 1 >= 0 && end + 1 < s.length() && s.charAt(start - 1) == s.charAt(end + 1)) { + start--; + end++; + } + if (rst.length() < s.substring(start, end + 1).length()) { + rst = s.substring(start, end + 1); + } + return rst; + } +} + /* O(n^2) Thoughts: @@ -44,3 +94,7 @@ public String longestPalindrome(String s) { return maxStr; } } + + + +``` \ No newline at end of file diff --git a/Java/Longest Substring Without Repeating Characters.java b/Java/Longest Substring Without Repeating Characters.java old mode 100644 new mode 100755 index b1cc0cc..6b1fe0e --- a/Java/Longest Substring Without Repeating Characters.java +++ b/Java/Longest Substring Without Repeating Characters.java @@ -1,3 +1,23 @@ +M + + +方法2:用两个pointer, head和i. + HashMap: + head从index 0 开始。若没有重复char, 每次只有for loop的i++。每次取substring[head,i]作为最新的string. + 一旦有重复,那么意味着,从重复的老的那个index要往后加一格开始。所以head = map.get(i) +1. + + +注意:head很可能被退回到很早的地方,比如abbbbbba,当遇到第二个a,head竟然变成了 head = 0+1 = 1. +当然这是不对的,所以head要确保一直增长,不回溯。 + + +方法1:只要有non-existing char就count++. 一旦有重复char: + i = 新出现重复Char的位置. + 重新init HashMap, count. + +这个方法每次都把map打碎重来, 是可以的,也没什么不好。就是在for里面改i,自己觉得不太顺.方法二可能顺一点。 + + ``` /* @@ -16,18 +36,44 @@ */ /* -Attempt1: What are you 弄啥唻?我第一个attempt每次遇到duplicate都打碎重来,我期待着这个时间pass不了啊..虽然硬跑的逻辑是说得通的。 + 02.02.2016 + Attempt2, Thoughts: + HashMap map + When char re-appear in map, 1. move head to repeating char's index + 1, 2. renew map with current index -Thoughts: + Note: head could repeat in earlier index, so make sure head does not travel back +*/ + +public class Solution { + public int lengthOfLongestSubstring(String s) { + if (s == null || s.length() == 0) { + return 0; + } + HashMap map = new HashMap(); + int head = 0; + int max = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (map.containsKey(c)) { + if (map.get(c) + 1 > head) {//make sure head does not travel back + head = map.get(c) + 1; + } + } + map.put(c, i); + String str = s.substring(head, i + 1); + max = Math.max(max, str.length()); + } + return max; + } +} + +/* +Attempt1, Thoughts: Loop the string, HashSet to store the Character, count++, and use a max to store longest length. Whenever a char exist in hashset, new hashset and count = 0, set i = 1st duplicate char, followed by i++, now start again. */ public class Solution { - /** - * @param s: a string - * @return: an integer - */ public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) { return 0; diff --git a/Java/Longest Substring with At Most K Distinct Characters.java b/Java/Longest Substring with At Most K Distinct Characters.java old mode 100644 new mode 100755 index acce12d..8b38f2e --- a/Java/Longest Substring with At Most K Distinct Characters.java +++ b/Java/Longest Substring with At Most K Distinct Characters.java @@ -1,13 +1,15 @@ -大清洗。 -map.size一旦超标,要把longest string最开头(marked by pointer:start)的那个char抹掉,而且要把它所有的appearance都抹掉;这样还不够,它最后一次出现以前的其他所有chars,也都要抹掉。 -大清洗的原因是: 一旦某一个char要被清除,由于substring必须是连续的,所以在它之前的所有chars都要被清洗。 -我去,黑帮大哥除龙头啊。 -简直就是要消灭伏地魔的7个魂器。 +M + +大清洗 O(nk) +map.size一旦>k,要把longest string最开头(marked by pointer:start)的那个char抹掉 +一旦某一个char要被清除,所以在这个char 的1st and last appearance之间的char都要被清洗from map + + + ``` /* Given a string s, find the length of the longest substring T that contains at most k distinct characters. -Have you met this question in a real interview? Yes Example For example, Given s = "eceba", k = 3, @@ -16,10 +18,12 @@ Challenge O(n), n is the size of the string s. -Tags Expand +Tags Expand String Two Pointers LintCode Copyright Hash Table + */ + /* Thoughts: HashMap size cannot go over k. @@ -33,11 +37,6 @@ Therefore, we need erase that particular char and all other chars before that particular char's last apperance. */ public class Solution { - /** - * @param s : A string - * @return : The length of the longest substring - * that contains at most k distinct characters. - */ public int lengthOfLongestSubstringKDistinct(String s, int k) { if (s == null || s.length() == 0 || k <= 0) { return 0; @@ -71,4 +70,16 @@ public int lengthOfLongestSubstringKDistinct(String s, int k) { } } + + +/* + 3.1.2016. + How about map to store last occurance of each char. + Use pointer head to show which char to cut off from string + + Not work: still has to clean up all chars that being cut off from the map, which is O(n) again. + So the solutoin has to be O(nk) +*/ + + ``` \ No newline at end of file diff --git a/Java/Lowest Common Ancestor II.java b/Java/Lowest Common Ancestor II.java old mode 100644 new mode 100755 index a497eff..bde0ade --- a/Java/Lowest Common Ancestor II.java +++ b/Java/Lowest Common Ancestor II.java @@ -1,7 +1,16 @@ -1. 曾经做的hashset的优化,找到的都存hashset. exist就return那个duplicate +E + +这个题有个奇葩的地方,每个node还有一个parent。 所以可以自底向上. + +1. 曾经做的hashset的优化,找到的都存hashset. exist就return那个duplicate. + + +2. 普通做法:2 lists。 + 自底向上。利用parent往root方向返回。 + +注意:无法从root去直接搜target node 而做成两个list. 因为根本不是Binary Search Tree! -2. 正常做法:2 lists ``` /* Lowest Common Ancestor II @@ -46,11 +55,6 @@ Find the lowest common ancestor(LCA) of the two nodes. */ public class Solution { - /** - * @param root: The root of the tree - * @param A, B: Two node in the tree - * @return: The lowest common ancestor of A and B - */ public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, ParentTreeNode A,ParentTreeNode B) { if (root == null || (A == null && B == null)) { @@ -100,11 +104,6 @@ public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, * } */ public class Solution { - /** - * @param root: The root of the tree - * @param A, B: Two node in the tree - * @return: The lowest common ancestor of A and B - */ public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, ParentTreeNode A, ParentTreeNode B) { diff --git a/Java/Lowest Common Ancestor of a Binary Search Tree.java b/Java/Lowest Common Ancestor of a Binary Search Tree.java new file mode 100755 index 0000000..953295c --- /dev/null +++ b/Java/Lowest Common Ancestor of a Binary Search Tree.java @@ -0,0 +1,84 @@ +M + +利用 BST的性质,可以直接搜到target node,而做成两个长度不一定相等的list。然后很简单找到LCA + + +``` +/* +Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. + +According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined +between two nodes v and w as the lowest node in T that has both v and w as descendants +(where we allow a node to be a descendant of itself).” + + _______6______ + / \ + ___2__ ___8__ + / \ / \ + 0 _4 7 9 + / \ + 3 5 +For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. +Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition. + +Tags: Tree +Similar Problems: (M) Lowest Common Ancestor of a Binary Tree + +*/ +/* +Thoughts: +Create 2 path: l1, l2. +First different node's parent, will be the LCA +Do binary search to generate the path l1,l2 + +Note: +When one of the target is root, make sure parent = root, and return root at the end. This is because: the if statement (l1.get(i).val != l2.get(i).val) won't capture this case; instead, the for loop ends by i == size. So, be careful here. +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || p == null || q == null) { + return null; + } + ArrayList l1 = new ArrayList(); + ArrayList l2 = new ArrayList(); + binarySearch(root, p, l1); + binarySearch(root, q, l2); + + TreeNode parent = root; + int size = l1.size() > l2.size() ? l2.size() : l1.size(); + for (int i = 0; i < size; i++) { + if (l1.get(i).val == l2.get(i).val) { + parent = l1.get(i); + } else { + return parent; + } + } + return parent; + } + + + public void binarySearch(TreeNode root, TreeNode target, ArrayList list) { + TreeNode node = root; + while (node != null) { + list.add(node); + if (node.val == target.val) { + return; + } else if (node.val < target.val) { + node = node.right; + } else { + node = node.left; + } + }//END while + } +} +``` \ No newline at end of file diff --git a/Java/Lowest Common Ancestor.java b/Java/Lowest Common Ancestor.java old mode 100644 new mode 100755 index 33c4e51..1ae6b8d --- a/Java/Lowest Common Ancestor.java +++ b/Java/Lowest Common Ancestor.java @@ -1,5 +1,23 @@ +E + +普通的Binary Tree,node child 自顶向下蔓延。 + +方法1:O(1) sapce O(h). Recursive. 循环的截点是: +当root == null或者 A B 任何一个在findLCA底部被找到了(root== A || root == B),那么就return 这个root. + +三种情况: +1. A,B都找到,那么这个level的node就是其中一层的parent。其实,最先recursively return到的那个,就是最底的LCA parent. +2. A 或者 B 找到,那就还没有公共parent,return 非null得那个。 +3. A B 都null, 那就找错了没有呗, return null + + +//无法找到target element, 因为不是Binary Search Tree +//[Not Working]:O(n) space O(h) time。把两条线binary search出来。找第一个不同的parent. 代码长。 Iterative + +``` + /* -33% Accepted + Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes. The lowest common ancestor is the node with largest depth which is the ancestor of both nodes. @@ -35,7 +53,7 @@ Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(L We divide and coquer (in this case DFS) into 2 branches, and we are actually asking each node to check: Do I have a leaf child of nodeA (could be futher down in the tree)? Do I have a leaf child of nodeB (could be futher down in the tree)? - 1. If I have leaf child of A && B, then i'm the deepest parent! Return. + 1. If I have leaf child of A && B, then i'm the deepest parent in line! Return. 2. If I only have A, or B: mark myself as an ancestor of A or B. 3. If I don't have leaf child of A nor B, I'm not an ancestor, failed, return null. @@ -98,17 +116,7 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { When it returns to the top, return solution : ancestor */ -/** - * Definition of TreeNode: - * public class TreeNode { - * public int val; - * public TreeNode left, right; - * public TreeNode(int val) { - * this.val = val; - * this.left = this.right = null; - * } - * } - */ + public class Solution { /** * @param root: The root of the binary search tree. @@ -133,3 +141,17 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { } } } + + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +``` diff --git a/Java/Majority Number II.java b/Java/Majority Number II.java old mode 100644 new mode 100755 index 91b1d96..b429724 --- a/Java/Majority Number II.java +++ b/Java/Majority Number II.java @@ -1,3 +1,12 @@ +M + +分三份:a b c考虑。若a, countA++, 或b, countB++,或c,countA--,countB--. + +最后出现的两个count>0的a和b,自然是potentially大于1/3的。其中有一个大于1/3. + +比较a和b哪个大,就return哪一个。 + +``` /* Given an array of integers, the majority number is the number that occurs more than 1/3 of the size of the array. @@ -12,23 +21,17 @@ Challenge O(n) time and O(1) space +*/ + +/* + Thinking process: Need to think the relations of 3 parts of the array: -1. Assume a > 1/3, which is the candidate were are looking for - However, only konwing a appears more than 1/3 of the array, does not mean there is no other element appears more than 1/3, for example, aaaaabcccccc, a = 5/12, b = 6/12. The majority is b. -2. Consider another element b, which is a different element rather than a. Discuss the 2 conditions of b. -3. Consider the rest of the array is in set c, which can contain all different elements. +1. Consider a and b. +2. Consider the rest of the array is in set c, which can contain all different elements. +3. Two if statement makes sure a and b fall into 1/3 of the conditions. Discuss relations between a, b, c -Assume a > 1/3 -Case1: b < 1/3 - given: a > 1/3, means b + c < 2/3, known b < 1/3 - get: c < 1/3 - conclusion: a is the majority -Case2: b > 1/3 - given: a + b ? 2/3 - get: c < 1/3 - conclusion: return the greater element# of a or b Implementation: 1. Have valA and valB two pointers to represent a and between @@ -37,12 +40,7 @@ 4. Note: at each index i, only one of valA or valB is checked. That means, we evaluate a and b individually against the section c. 5. At the end, we found 2 candidates: a and b. Now compare the # of a and b to see which is greater. */ - public class Solution { - /** - * @param nums: A list of integers - * @return: The majority number that occurs more than 1/3 - */ public int majorityNumber(ArrayList nums) { if (nums == null || nums.size() == 0) { return -1; @@ -81,3 +79,5 @@ public int majorityNumber(ArrayList nums) { } } + +``` \ No newline at end of file diff --git a/Java/Majority Number III.java b/Java/Majority Number III.java old mode 100644 new mode 100755 index 70f58d0..b8bb1f6 --- a/Java/Majority Number III.java +++ b/Java/Majority Number III.java @@ -1,5 +1,17 @@ +M + +与其他Majority Number一样。 + +出现次数多余1/k,就要分成k份count occurance.用HashMap。 存在的+1;不存在map里的,分情况: +若map.size() == k,说明candidate都满了,要在map里把所有现存的都-1; +若map.size() < k, 说明该加新candidate,那么map.put(xxx, 1); + +最后在HashMap里找出所留下的occurance最大的那个数。 + +``` /* -Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array. Find it. +Given an array of integers and a number k, the majority number is the number +that occurs more than 1/k of the size of the array. Find it. Note There is only one majority number in the array. @@ -10,6 +22,9 @@ Challenge O(n) time and O(k) extra space +*/ + +/* Thinking process: Very similar to Majority I, II, except we can use a HashMap to store information (value, count). Having a HashMap we have one advantage: when checking if current value matches any previously recorded val, just do a map.containsKey(val). @@ -17,15 +32,9 @@ Very similar to Majority I, II, except we can use a HashMap to store information Note, to learn how to use iterator in HashMap. Note: when map.containsKey(currVal) == false, the code checks map.size() == k before count-- perations. This is because: We first need to put k candidates into HashMap before we count-- from all of them. If map.size() < k, that means we still have free spot for candidate in the HashMap, so in this case we do: map.put(candidateKey, 1). -*/ - +*/ public class Solution { - /** - * @param nums: A list of integers - * @param k: As described - * @return: The majority number - */ public int majorityNumber(ArrayList nums, int k) { if (nums == null || nums.size() == 0) { return -1; @@ -35,7 +44,7 @@ public int majorityNumber(ArrayList nums, int k) { if (map.containsKey(num)) {//Found duplicates, count++ map.put(num, map.get(num) + 1); } else { - if (map.size() == k) {//All candidates added, do count-- + if (map.size() == k) {//Enough candidates added, do count-- Iterator> iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -63,3 +72,5 @@ public int majorityNumber(ArrayList nums, int k) { } } + +``` \ No newline at end of file diff --git a/Java/Majority Number.java b/Java/Majority Number.java old mode 100644 new mode 100755 index 600d71f..02a0afa --- a/Java/Majority Number.java +++ b/Java/Majority Number.java @@ -1,3 +1,15 @@ +E + +Majority Number是指超半数。任何超半数,都可以用0和1count:是某个number,+1;不是这个number,-1. + +注意:assume valid input, 是一定有一个majority number的。否则此法不成。[1,1,1,2,2,2,3]是个invalid input,结果是3,当然也错了。 + +Majority Number II,超1/3, 那么就分三份处理,countA, countB来计算最多出现的两个。 + +Majority Number III, 超1/k, 那么自然分k份。这里用到 HashMap。 + +``` + /* Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it. @@ -9,6 +21,10 @@ Tag: Enumeration + +*/ + +/* Thinking process: Natural thinking process: count how many you have for 1st element, if next one is the same, count++, if next one is not the same, count- -. When count ==0, that means other types of element has same amount as the 1st majority number, they are even. @@ -16,7 +32,6 @@ Note: this solutions works only when the given array has a valid solution. CounterCase:[111223], with actually return 3 as the majority number. But again, this is not a valid input in this case. */ - public class Solution { /** * @param nums: a list of integers @@ -43,3 +58,5 @@ public int majorityNumber(ArrayList nums) { } } + +``` \ No newline at end of file diff --git a/Java/Matrix Zigzag Traversal.java b/Java/Matrix Zigzag Traversal.java old mode 100644 new mode 100755 index 629772f..8a3f6ce --- a/Java/Matrix Zigzag Traversal.java +++ b/Java/Matrix Zigzag Traversal.java @@ -1,5 +1,8 @@ -分析4个step. -小心走位。 +E + +分析4个step:right, left-bottom,down,right-up +implement时注意index.有点耐心 + ``` /* Matrix Zigzag Traversal diff --git a/Java/Max Tree.java b/Java/Max Tree.java old mode 100644 new mode 100755 index 693fa14..779e996 --- a/Java/Max Tree.java +++ b/Java/Max Tree.java @@ -1,10 +1,23 @@ -MaxTree值得记。 -Stack从下到上,最大在下。维持和利用这个性质: -把所有小于curr node的,全Pop出来,最后一个小于Curr的,放在curr.left. -接下去stack里面的一定是大于curr,那就变成curr的left parent. +H + +Should memorize MaxTree. 依次类推,会做Min-Tree, Expression Tree + +Stack里,最大的值在下面。利用此性质,有这样几个step: + +1 +把所有小于curr node的,全Pop出来, while loop, keep it going. +最后pop出的这个小于Curr的node:它同时也是stack里面pop出来小于curr的最大的一个,最接近curr大小。(因为这个stack最大值靠下面) +把这个最大的小于curr的node放在curr.left. + +2 +那么,接下去stack里面的一定是大于curr: +那就变成curr的left parent. set stack.peek().right = curr. + +3 结尾:stack底部一定是最大的那个,也就是max tree的头。 -妙啊!!! + + ``` /* Given an integer array with no duplicates. A max tree building on this array is defined as follow: @@ -13,7 +26,6 @@ The left subtree and right subtree are the max trees of the subarray divided by the root number. Construct the max tree by the given array. -Have you met this question in a real interview? Yes Example Given [2, 5, 6, 0, 3, 1], the max tree constructed by this array is: @@ -50,34 +62,7 @@ All smaller element (smaller than current point) will be poped out, */ -/** - * Definition of TreeNode: - * public class TreeNode { - * public int val; - * public TreeNode left, right; - * public TreeNode(int val) { - * this.val = val; - * this.left = this.right = null; - * } - * } - */ -/* - -Given [2, 5, 6, 0, 3, 1], the max tree constructed by this array is: - - 6 - / \ - 5 3 - / / \ -2 0 1 -Challenge - -*/ public class Solution { - /** - * @param A: Given an integer array with no duplicates. - * @return: The root of max tree. - */ public TreeNode maxTree(int[] A) { if (A == null || A.length == 0) { return null; @@ -102,4 +87,18 @@ public TreeNode maxTree(int[] A) { } } + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + ``` \ No newline at end of file diff --git a/Java/Maximal Square.java b/Java/Maximal Square.java index c3048fa..fd858f9 100644 --- a/Java/Maximal Square.java +++ b/Java/Maximal Square.java @@ -1,7 +1,16 @@ -从边长为2的正方形看起,看左上角的那个点。 -如何确定是个正方形?首先看左上点是不是1,然后看右边,右下,下面的点是不是1. -DP就是根据这个特征想出来。dp[i,j]代表从右下推上来,包括当前点的,所积累的最长边。 -注意dp[i,j]被右,右下,下三点的最短点所限制。这就是fn. +M + +DP问题 + +从边长为2的正方形看起,看左上角的那个点。 +如何确定是个正方形?首先看左上点是不是1,然后看右边,右下,下面的点是不是1. + +DP就是根据这个特征想出来。dp[i,j]: 从右下往左上推算,包括当前点在内的所能找到的最大边长。 + 注意dp[i,j]被右边,右下,下面三点的最短点所限制。这就是fn. + +Init: + 把右边,下边两个边缘init一遍,存matrix在这两条边上的值,代表的意思也就是dp[i][j]在这些点上的初始值:变成为1 or 0. + ``` /* Given a 2D binary matrix filled with 0's and 1's, @@ -24,12 +33,12 @@ Thoughts: Seem that we need to check on right and bottom spots for 2x2 1's. If all size spots are clean, len++, square = newLen ^ 2. DP[i,j]: the longest square lengh that this matrix[i][j] reach. - dp[i,j] = Math.min(dp[i][j+1], dp[i+1][j], dp[i][j]) + dp[i,j] = Math.min(dp[i][j+1], dp[i+1][j], dp[i+1][j+1]) init: dp[n-1][0 ~ m-1] = matrix[n-1][0 ~ m-1] == 0 ? 0 : 1; dp[0 ~ n-1][m-1] = matrix[0 ~ n-1][m-1] == 0 ? 0 : 1; for from rigt-bottom conor. - Maintain a max are + Maintain a max area */ public class Solution { diff --git a/Java/Maximum Depth of Binary Tree.java b/Java/Maximum Depth of Binary Tree.java index 6e01816..c07799b 100644 --- a/Java/Maximum Depth of Binary Tree.java +++ b/Java/Maximum Depth of Binary Tree.java @@ -1,5 +1,7 @@ -DFS -Divide and conquer +E + +DFS: Divide and conquer. 维持一个最大值。 + ``` /* 71% Accepted @@ -59,5 +61,14 @@ public int maxDepth(TreeNode root) { } } +//Find all depth and return max alone the way +public class Solution { + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; + } +} ``` \ No newline at end of file diff --git a/Java/Median of two Sorted Arrays.java b/Java/Median of two Sorted Arrays.java index 09b843f..4d8c892 100644 --- a/Java/Median of two Sorted Arrays.java +++ b/Java/Median of two Sorted Arrays.java @@ -1,8 +1,14 @@ +H + +Not done + +``` /* Median of two Sorted Arrays -There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. +There are two sorted arrays A and B of size m and n respectively. +Find the median of the two sorted arrays. Example Given A=[1,2,3,4,5,6] and B=[2,3,4,5], the median is 3.5. @@ -18,12 +24,25 @@ The overall run time complexity should be O(log (m+n)). */ /* - Thoughts: - Trivial: merge and find median. NOPE: have to be in log(m+n) time - http://www.jiuzhang.com/solutions/median-of-two-sorted-arrays/ +From leetcode: +There are two sorted arrays nums1 and nums2 of size m and n respectively. +Find the median of the two sorted arrays. +The overall run time complexity should be O(log (m+n)). + +Hide Company Tags Google Uber Zenefits +Hide Tags Divide and Conquer Array Binary Search + +*/ +/* + Thoughts: + Trivial: merge and find median. NOPE: have to be in log(m+n) time + http://www.jiuzhang.com/solutions/median-of-two-sorted-arrays/ + + http://articles.leetcode.com/find-k-th-smallest-element-in-union-of + + Good one: http://blog.csdn.net/yutianzuijin/article/details/11499917 + http://blog.csdn.net/zxzxy1988/article/details/8587244 - http://fisherlei.blogspot.com/2012/12/leetcode-median-of-two-sorted-arrays.html - */ class Solution { @@ -37,3 +56,5 @@ public double findMedianSortedArrays(int[] A, int[] B) { } } + +``` \ No newline at end of file diff --git a/Java/Meeting Rooms II.java b/Java/Meeting Rooms II.java new file mode 100755 index 0000000..5d7a8e1 --- /dev/null +++ b/Java/Meeting Rooms II.java @@ -0,0 +1,123 @@ +M + + +方法1:PriorityQueue + 一个Class来解决。O(nlogn) + +方法2:这里有尝试了一下用一个sorted Array + HashMap: 也还行,但是handle edge的时候,HashMap 要小心,因为相同时间start和end的map key 就会重复了。 + +``` +/* +Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), +find the minimum number of conference rooms required. + +For example +Given [[0, 30],[5, 10],[15, 20]], +return 2. + +Tags: Heap Greedy Sort +Similar Problems: (H) Merge Intervals, (E) Meeting Rooms +*/ + + + + +// Similar to Meeting Room I, using Point class and Priorityqueue +// Creating a customized class, but makes the problem a bit easier to think. +public class Solution { + class Point { + int pos, flag; + public Point(int pos, int flag) { + this.pos = pos; + this.flag = flag; + } + } + public int minMeetingRooms(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return 0; + } + + PriorityQueue queue = new PriorityQueue(2, new Comparator() { + public int compare(Point p1, Point p2) { + return p1.pos - p2.pos; + } + }); + + for (int i = 0; i < intervals.length; i++) { + queue.offer(new Point(intervals[i].start, 1)); + queue.offer(new Point(intervals[i].end, -1)); + } + int count = 0; + int rst = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count += p.flag; + while (!queue.isEmpty() && p.pos == queue.peek().pos) { + p = queue.poll(); + count += p.flag; + } + rst = Math.max(count, rst); + } + + return rst; + } +} + +/* +Thoughts: This seems to be: how many concurrent meetings do we have? +Just return the count that we used in Meeting I. + +Though, instead of Prority queue + Point class, let me try to use just array and a hashmap. + +Using HashMap is tricky in this: +Overallpping spot will be put on the same hashmap key. Be careful with handling the overlapping. +Here, I decide to merge the edge when generate the map, so during the count check, need to skip +duplicated time spot to prevent incorrectly re-use of certain time spot. + + +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ +public class Solution { + public int minMeetingRooms(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return 0; + } + int[] timeSpot = new int[intervals.length * 2]; + HashMap map = new HashMap(); + for (int i = 0; i < intervals.length; i++) { + timeSpot[i] = intervals[i].start; + timeSpot[intervals.length + i] = intervals[i].end; + if (map.containsKey(intervals[i].start)) { + map.put(intervals[i].start, map.get(intervals[i].start) + 1); + } else { + map.put(intervals[i].start, 1); + } + if (map.containsKey(intervals[i].end)) { + map.put(intervals[i].end, map.get(intervals[i].end) - 1); + } else { + map.put(intervals[i].end, -1); + } + } + Arrays.sort(timeSpot); + int count = 0; + int max = 0; + for (int i = 0; i < timeSpot.length; i++) { + count += map.get(timeSpot[i]); + while (i + 1 < timeSpot.length && timeSpot[i] == timeSpot[i + 1]) { + i++; + } + max = Math.max(count, max); + } + return max; + } +} + +``` \ No newline at end of file diff --git a/Java/Meeting Rooms.java b/Java/Meeting Rooms.java new file mode 100755 index 0000000..7635ce3 --- /dev/null +++ b/Java/Meeting Rooms.java @@ -0,0 +1,79 @@ +E + +Scan line, class Point{pos, flag}, PriorityQueue排序。计算count + +注意接头点要考虑所有开会结会的情况,不要恰巧漏掉相接的点。 +开会的是超人。瞬间移动接上下一个会议。 + +``` +/* +Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), +determine if a person could attend all meetings. + +For example, +Given [[0, 30],[5, 10],[15, 20]], +return false. + +Hide Company Tags Facebook +Hide Tags Sort +Hide Similar Problems (H) Merge Intervals (M) Meeting Rooms II + +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ + +/* +Thought: +Use scan line. +Note: special care for edge point: make sure to process all connecting point before shuouting the result. +*/ + + //use scan line +public class Solution { + class Point { + int pos, flag; + public Point(int pos, int flag) { + this.pos = pos; + this.flag = flag; + } + } + public boolean canAttendMeetings(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return true; + } + + PriorityQueue queue = new PriorityQueue(2, new Comparator() { + public int compare(Point p1, Point p2) { + return p1.pos - p2.pos; + } + }); + + for (int i = 0; i < intervals.length; i++) { + queue.offer(new Point(intervals[i].start, 1)); + queue.offer(new Point(intervals[i].end, -1)); + } + int count = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count += p.flag; + while (!queue.isEmpty() && p.pos == queue.peek().pos) { + p = queue.poll(); + count += p.flag; + } + if (count > 1) { + return false; + } + } + + return true; + } +} +``` \ No newline at end of file diff --git a/Java/Merge Intervals.java b/Java/Merge Intervals.java old mode 100644 new mode 100755 index 518bf89..8d1a034 --- a/Java/Merge Intervals.java +++ b/Java/Merge Intervals.java @@ -1,73 +1,160 @@ +E + +方法1:O(nlogn) +扫描线+Count无敌手。注意start end把interval给合起来。 +count==0的时候,就是每次start end双数抵消的时候,就应该是一个interval的开头/结尾。写个例子就知道了。 + +空间:O(2n) -> O(n) +时间,priorityqueue: O(nlogn) + +记得怎么写comparator + +在 LeetCode里面,Scan line比方法2要快很多. + +方法2: +Collections.sort() on interval.start之后,试着跑一遍,按照merge的需求,把需要merge的地方续好,然后减掉多余的interval就好。 + +(不知为何LeetCode把Merge Interval, Insert Interval 标为Hard) + +Collections.sort(..., new comparator): sort by Interval.start. + +画两个相连的Interval, prev, curr: +prev只有 prev.end覆盖了 curr.start, 才需要merge. 那么比较一下, marege. +记得如果merge, 一定要list.remove(i), 并且i--, 因为改变了List的大小。 + +若没有重合,就继续iteration: prev = curr. move on. + /* + new Comparator(){ + public int compare(obj1, obj2) { + return obj1.x - obj2.x; + } + } +*/ + + +``` +/* Given a collection of intervals, merge all overlapping intervals. -Example -Given intervals => merged intervals: +For example, +Given [1,3],[2,6],[8,10],[15,18], +return [1,6],[8,10],[15,18]. -[ [ - [1, 3], [1, 6], - [2, 6], => [8, 10], - [8, 10], [15, 18] - [15, 18] ] -] -Challenge -O(n log n) time and O(1) extra space. +Tags: Array, Sort +Similar Problems: (H) Insert Interval, (E) Meeting Rooms (M) Meeting Rooms II -Tags Expand -Sort Array +*/ +/* Thoughts: -1. use comparator to sort list. Well, no need to create a new class. Just do it inline. -2. iterate through the list and merge (whenever there is overlap) - +Again use scan line. Quite similar to Meeting Rooms, flight schedules... etc +This one: when count ==0, make sure to keep track start and end, add into the rst +When writing out example, whenever count==0, that indicates an end of a interval. -Review: -List: size(), get(..), remove(..) -Comparator +HOWEVER, this uses O(n) space, while this problem requests O(1) space */ - /** - * Definition of Interval: + * Definition for an interval. * public class Interval { - * int start, end; - * Interval(int start, int end) { - * this.start = start; - * this.end = end; - * } + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } */ +public class Solution { + class Point{ + int x, flag; + public Point(int x, int flag) { + this.x = x; + this.flag = flag; + } + } + public List merge(List intervals) { + List rst = new ArrayList(); + if (intervals == null || intervals.size() == 0) { + return rst; + } + PriorityQueue queue = new PriorityQueue(2, new Comparator() { + public int compare(Point p1, Point p2) { + return p1.x - p2.x; + } + }); + + for (Interval entry : intervals) { + queue.offer(new Point(entry.start, 1)); + queue.offer(new Point(entry.end, -1)); + } + + int count = 0; + int start = 0; + int end = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + if (count == 0) {//detect start + start = p.x; + } + count += p.flag; + while (!queue.isEmpty() && p.x == queue.peek().x) {//proces all points on same position x + p = queue.poll(); + count += p.flag; + } + if (count == 0) {//detect end + end = p.x; + rst.add(new Interval(start, end)); + } + } + + return rst; + } +} + + + +/* + Thoughts: 12.09.2015 + Recap. Use O(1) + + Sort by start time. + then it overlaps: check on pre.end and curr.start. + if overlaps: curr.start will be overlapped; also check on curr.end and pre.end, decide who ends this interval + + border case: null, return itself; or length==1, return. +*/ class Solution { - /** - * @param intervals: Sorted interval list. - * @return: A new sorted interval list. - */ public List merge(List intervals) { - if (intervals == null || intervals.size() == 0) { - return intervals; + if (intervals == null || intervals.size() <= 1) { + return intervals; } - // intervals.sort(new CustomComparator()); Collections.sort(intervals, new Comparator(){ - public int compare(Interval a, Interval b){ - return a.start - b.start; - } + public int compare(Interval a, Interval b) { + return a.start - b.start; + } }); - //Merge - Interval pre = intervals.get(0); - Interval curr = null; + Interval prev = intervals.get(0); + Interval curr; + for (int i = 1; i < intervals.size(); i++) { - curr = intervals.get(i); - if (pre.end >= curr.start) { - pre.end = pre.end > curr.end ? pre.end : curr.end; - intervals.remove(i); - i--; - } else { - pre = curr; - } + curr = intervals.get(i); + if (prev.end >= curr.start) { + if (prev.end <= curr.end) { + prev.end = curr.end; + } + intervals.remove(i); + i--; + } else { + prev = curr; + } } - + return intervals; } + } + +``` \ No newline at end of file diff --git a/Java/Merge Sorted Array.java b/Java/Merge Sorted Array.java index 2fdf188..ba2cc22 100644 --- a/Java/Merge Sorted Array.java +++ b/Java/Merge Sorted Array.java @@ -1,21 +1,44 @@ -A够长,那么可以从A的尾部开始加新元素。 -注意,从尾部,是大数字优先的。 +E + +A够长,那么可以从A的尾部开始加新元素。 +注意,从尾部,是大数字优先的。 + ``` /* -Given two sorted integer arrays A and B, merge B into A as one sorted array. - -Note -You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements initialized in A and B are mand n respectively. +Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. -Example -A = [1, 2, 3, empty, empty] B = [4,5] +Note: +You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively. -After merge, A will be filled as [1,2,3,4,5] +Hide Company Tags Bloomberg Facebook +Hide Tags Array Two Pointers +Hide Similar Problems (E) Merge Two Sorted Lists -Tags Expand -Array Sorted Array */ +/*Recap 02.17.2015*/ +//merge from m + n position +public class Solution { + public void merge(int[] nums1, int m, int[] nums2, int n) { + if (nums1 == null || nums2 == null) { + return; + } + int ind1 = m - 1; + int ind2 = n - 1; + for (int i = m + n - 1; i >= 0; i--) { + if ((ind1 >= 0 && ind2 >= 0 && nums1[ind1] >= nums2[ind2]) + || (ind1 >= 0 && ind2 < 0)) { + nums1[i] = nums1[ind1]; + ind1--; + } else if ((ind1 >= 0 && ind2 >= 0 && nums1[ind1] < nums2[ind2]) + || (ind1 < 0 && ind2 >= 0)) { + nums1[i] = nums2[ind2]; + ind2--; + } + } + } +} + /* Thinking process: 1. start from the end, track back. End index = m + n; @@ -23,12 +46,6 @@ You may assume that A has enough space (size that is greater or equal to m + n) 3. Make sure to clean up the second array B. */ class Solution { - /** - * @param A: sorted integer array A which has m elements, - * but size of A is m+n - * @param B: sorted integer array B which has n elements - * @return: void - */ public void mergeSortedArray(int[] A, int m, int[] B, int n) { // write your code here int index = m + n; diff --git a/Java/Merge Two Sorted List.java b/Java/Merge Two Sorted List.java index 92363b1..c793817 100644 --- a/Java/Merge Two Sorted List.java +++ b/Java/Merge Two Sorted List.java @@ -1,7 +1,10 @@ -小的放前。每次比head大小。 -while过后,把没完的list一口气接上。 +E + +小的放前。每次比head大小。 +while过后,把没完的list一口气接上。 一开始建一个node用来跑路, 每次都存node.next = xxx。存一个dummy。用来return dummy.next. + ``` /* 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. diff --git a/Java/Merge Two Sorted Lists.java b/Java/Merge Two Sorted Lists.java new file mode 100644 index 0000000..e31e208 --- /dev/null +++ b/Java/Merge Two Sorted Lists.java @@ -0,0 +1,50 @@ +/* +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. + +Tags: Linked List +Similar Problems: (H) Merge k Sorted Lists, (E) Merge Sorted Array, (M) Sort List, (M) Shortest Word Distance II + +*/ + +/* +Thouhts: +Loop throgh both list. Make sure to check the border cases +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } + ListNode node = new ListNode(0); + ListNode dummy = node; + while (l1 != null || l2 != null) { + if (l1 == null) { + node.next = l2; + break; + } else if (l2 == null) { + node.next = l1; + break; + } else { + if (l1.val < l2.val) { + node.next = l1; + l1 = l1.next; + } else { + node.next = l2; + l2 = l2.next; + } + node = node.next; + } + }//end while + return dummy.next; + } +} \ No newline at end of file diff --git a/Java/Merge k Sorted Arrays.java b/Java/Merge k Sorted Arrays.java index 2a64dcc..3d9105d 100644 --- a/Java/Merge k Sorted Arrays.java +++ b/Java/Merge k Sorted Arrays.java @@ -1,5 +1,10 @@ -由Merge k linked list想到,有办法找到每个node的sibling, 而int[]又不行,所以: -自己建立一个class 来存放必要信息 +M + +由Merge k sorted list启发。用PriorityQueue,存那k个首发element。 + +PriorityQueue需要存储单位。自己建一个Class Node 存val, x,y index. +因为array里没有 'next' pointer,只能存x,y来推next element + ``` /* Given k sorted integer arrays, merge them into one sorted array. @@ -80,18 +85,4 @@ public int compare(Node a, Node b){ } - - - - - - - - - - - - - - ``` \ No newline at end of file diff --git a/Java/Merge k Sorted Lists.java b/Java/Merge k Sorted Lists.java index c1b2e19..9330d6c 100644 --- a/Java/Merge k Sorted Lists.java +++ b/Java/Merge k Sorted Lists.java @@ -1,66 +1,93 @@ -用Priorityqueue来排列所有list的头头。 -非常正规的。 - -记得k lists 需要是已经sort好的。 - -时间:n*O(logk) -PriorityQueue: logk -这个题目可以有好几个衍生: - -比如,如果k很大,一个机器上放不下所有的k list怎么办? -比如,如果Merge起来的很长,一个机器上放不下怎么办? -``` -/* -22% 通过 -Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. - -样例 -标签 Expand -Linked List Divide and Conquer Heap - -*/ - -/* - 12.10.2015 recap - Use queue to store the head of k lists. - First init with all heads. - Because the ListNode always has a link to its next sibiling, so it's easy to add that sibling back to queue. -*/ -public class Solution { - public ListNode mergeKLists(List lists) { - if (lists == null || lists.size() == 0) { - return null; - } - PriorityQueue queue = - new PriorityQueue(lists.size(), new Comparator(){ - public int compare(ListNode a, ListNode b){ - return a.val - b.val; - } - }); - - //populate queue with k lists' header - for (int i = 0; i < lists.size(); i++) { - if (lists.get(i) != null) { - queue.offer(lists.get(i)); - } - } - - ListNode dummy = new ListNode(0); - ListNode node = dummy; - while (!queue.isEmpty()) { - ListNode curr = queue.poll(); - node.next = curr; - - if (curr.next != null) { - queue.offer(curr.next); - } - - node = node.next; - } - - return dummy.next; - } -} - - +M + +用Priorityqueue来排列所有list的leading node. + +记得k lists 需要是已经sort好的。 + +时间:n*O(logk) +PriorityQueue: logk + +这个题目可以有好几个衍生: + 比如,如果k很大,一个机器上放不下所有的k list怎么办? + 比如,如果Merge起来的很长,一个机器上放不下怎么办? + +``` + +/* + +Merge k sorted linked lists and return it as one sorted list. + +Analyze and describe its complexity. + + +Example +Given lists: + +[ + 2->4->null, + null, + -1->null +], +return -1->2->4->null. + +Tags Expand +Divide and Conquer Linked List Priority Queue Heap Uber Google Twitter LinkedIn Airbnb Facebook + + +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ + + +/* + 12.10.2015 recap + Use queue to store the head of k lists. + First init with all heads. + Because the ListNode always has a link to its next sibiling, so it's easy to add that sibling back to queue. + time: m * Log(k) +*/ +public class Solution { + public ListNode mergeKLists(List lists) { + if (lists == null || lists.size() == 0) { + return null; + } + PriorityQueue queue = + new PriorityQueue(lists.size(), new Comparator(){ + public int compare(ListNode a, ListNode b){ + return a.val - b.val; + } + }); + + //populate queue with k lists' header + for (int i = 0; i < lists.size(); i++) { + if (lists.get(i) != null) { + queue.offer(lists.get(i)); + } + } + + ListNode dummy = new ListNode(0); + ListNode node = dummy; + while (!queue.isEmpty()) { + ListNode curr = queue.poll(); + node.next = curr; + + if (curr.next != null) { + queue.offer(curr.next); + } + + node = node.next; + } + + return dummy.next; + } +} + + ``` \ No newline at end of file diff --git a/Java/Min Stack.java b/Java/Min Stack.java index 4dd69c5..9e7813c 100644 --- a/Java/Min Stack.java +++ b/Java/Min Stack.java @@ -1,3 +1,10 @@ +E + +双Stack:一个正常stack,另一个minStack存当下level最小值. 注意维护minStack的变化 + +另外. 如果要maxStack,也是类似做法 + +``` /* Implement a stack with min() function, which will return the smallest number in the stack. @@ -28,26 +35,28 @@ public class MinStack { private Stack stack; private Stack minStack; public MinStack() { - stack = new Stack(); - minStack = new Stack(); + stack = new Stack(); + minStack = new Stack(); } public void push(int number) { - stack.push(number); - if (minStack.isEmpty()) { - minStack.push(number); - } else { - minStack.push(minStack.peek() >= number ? number : minStack.peek()); - } + stack.push(number); + if (minStack.isEmpty()) { + minStack.push(number); + } else { + minStack.push(minStack.peek() >= number ? number : minStack.peek()); + } } public int pop() { - minStack.pop(); - return stack.pop(); + minStack.pop(); + return stack.pop(); } public int min() { - return minStack.peek(); + return minStack.peek(); } } + +``` \ No newline at end of file diff --git a/Java/Minimum Height Trees.java b/Java/Minimum Height Trees.java new file mode 100644 index 0000000..c1f3e10 --- /dev/null +++ b/Java/Minimum Height Trees.java @@ -0,0 +1,121 @@ +/* +For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. + +Format +The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). + +You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + +Example 1: + +Given n = 4, edges = [[1, 0], [1, 2], [1, 3]] + + 0 + | + 1 + / \ + 2 3 +return [1] + +Example 2: + +Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] + + 0 1 2 + \ | / + 3 + | + 4 + | + 5 +return [3, 4] + +Show Hint +Note: + +(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.” + +(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf. + +Credits: +Special thanks to @peisi for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Breadth-first Search Graph +Hide Similar Problems (M) Course Schedule (M) Course Schedule II + +*/ + + +/* + Starting from leaf with depth == 1, + remove all leaf, and the edge + Till the end, whatever node left, should be the root. + + * WHen there is only 1,2 nodes remaining. that's the rst. + + Put Node in HahsMap + + Iterative over map till map.size() <= 2 + + border n == 2,1, just returl rst. + edges == null, return null. + edges.length == 1, reutrn list +*/ + +public class Solution { + public List findMinHeightTrees(int n, int[][] edges) { + List rst = new ArrayList(); + if (n == 1) { + rst.add(0); + return rst; + }else if (n == 0 || edges == null || edges.length == 0 || edges.length != n - 1) { + return rst; + } + + //populate map + boolean[] nodes = new boolean[n]; + HashMap> map = new HashMap>(); + for (int i = 0; i < n; i++) { + map.put(i, new ArrayList()); + nodes[i] = true; + } + for (int i = 0; i < edges.length; i++) { + if (!map.get(edges[i][0]).contains(edges[i][1])) { + map.get(edges[i][0]).add(edges[i][1]); + } + if (!map.get(edges[i][1]).contains(edges[i][0])) { + map.get(edges[i][1]).add(edges[i][0]); + } + } + + //Remove list with leng == 1 + Queue queue = new LinkedList(); + while (n > 2) { + for (Map.Entry> entry : map.entrySet()) { + if (entry.getValue().size() == 1) { + queue.offer(entry.getKey()); + } + } + while (!queue.isEmpty()) { + n--; + Integer key = queue.poll(); + nodes[key] = false; + int from = map.get(key).get(0); + map.get(from).remove(key); + map.get(key).remove(0); + + } + } + + //Put remaining into rst + for (int i = 0; i < nodes.length; i++) { + if (nodes[i]) { + rst.add(i); + } + + } + + return rst; + } +} \ No newline at end of file diff --git a/Java/Minimum Size Subarray Sum.java b/Java/Minimum Size Subarray Sum.java old mode 100644 new mode 100755 index 4e81edd..9e66bf3 --- a/Java/Minimum Size Subarray Sum.java +++ b/Java/Minimum Size Subarray Sum.java @@ -1,11 +1,18 @@ -2 pointer: -一个做base, 每次动一格:i. -一个做前锋,加到满足条件为止。 -Note: 当sum >= s 条件在while里面满足时,end是多一个index的。所以result里面要处理好边缘情况:(end-1) 才是真的末尾位置,然后计算和开头的间隙: -(end - 1) - start + 1; +M + +2 pointer, O(n). 找subarray, start 或 end pointer,每次一格这样移动. + +好的策略: 先找一个solution, 定住end, 然后移动start; 记录每个solution if occurs; 然后再移动end,往下找。 + +Note: 虽然一眼看上去是nested loop.但是分析后,发现其实就是按照end pointer移动的Loop。start每次移动一格。总体上,还是O(n) + + +Note done the O(nlogn) yet + ``` /* -Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return -1 instead. +Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. +If there isn't one, return -1 instead. Example Given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length under the problem constraint. @@ -18,17 +25,54 @@ If you have figured out the O(n) solution, try coding another solution of which */ /* -Thoughts: +3.2.2016 +Clearner: +1. Move 'end' for first possbile solution +2. Store it and remove one 'start' element from sum. Save any solution if occurs, in while loop. +3. Go back to step 1, until 'end' hits nums.length +*/ + +public class Solution { + public int minimumSize(int[] nums, int s) { + if (nums == null || nums.length == 0) { + return -1; + } + int min = Integer.MAX_VALUE; + int start = 0; + int end = 0; + int sum = 0; + + while (end < nums.length) { + while (end < nums.length && sum < s) { + sum += nums[end]; + end++; + } + while (sum >= s) { + min = Math.min(min, end - start); + sum -= nums[start]; + start++; + } + } + return (min == Integer.MAX_VALUE) ? -1 : min; + } +} + + +/* +Thoughts: old solution O(n), not prefered. Create a subarray range: (i,j). Use i as start and j as end. Check if within the range, sum >= s. Shift the range every time: i += 1. + +2 pointer: +一个做base, 每次动一格:i. +一个做前锋,加到满足条件为止。 +Note: 当sum >= s 条件在while里面满足时,end是多一个index的。所以result里面要处理好边缘情况:(end-1) 才是真的末尾位置,然后计算和开头的间隙: +(end - 1) - start + 1; + + */ public class Solution { - /** - * @param nums: an array of integers - * @param s: an integer - * @return: an integer representing the minimum size of subarray - */ public int minimumSize(int[] nums, int s) { if (nums == null || nums.length == 0) { return -1; diff --git a/Java/Minimum Window Substring.java b/Java/Minimum Window Substring.java old mode 100644 new mode 100755 index dfaabcb..f13b58e --- a/Java/Minimum Window Substring.java +++ b/Java/Minimum Window Substring.java @@ -1,5 +1,19 @@ +H + +LeetCode Hard +LintCode M, 测试有问题,即使做错也能过. + +基本思想: 用个map存target的。 然后在搜索s的时候,遇到Match, frequency--. +一旦map里面的frequency都被减为0, 就说明找到candidate. + +有好几个trick:考虑start,前指针怎么移动;考虑start在candidate首字母没有多余前,不能移动;考虑candidate出现的情况... + +复习时,回去看别人网站和自己的thoughts + +``` /* -Given a string source and a string target, find the minimum window in source which will contain all the characters in target. +Given a string source and a string target, find the minimum window in source +which will contain all the characters in target. Example source = "ADOBECODEBANC" target = "ABC" Minimum window is "BANC". @@ -7,7 +21,8 @@ Note If there is no such window in source that covers all characters in target, return the emtpy string "". -If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in source. +If there are multiple such windows, you are guaranteed that +there will always be only one unique minimum window in source. Challenge Can you do it in time complexity O(n) ? @@ -19,7 +34,164 @@ Can you do it in time complexity O(n) ? Tags Expand Hash Table +*/ + +/* +03.09.2016 +http://blog.sina.com.cn/s/blog_eb52001d0102v2il.html +http://www.rudy-yuan.net/archives/185/ + +只利用一个hashmap save frequency of target. +1. 从map里面 减去 source char match target char 的frequency. 如果发现frequency = 0, size++ + size == map.size,说明有一个candidate. +2. 维持left,right pointer。 +记住一个规则: 如果map里面在left index上面的frequency >=0, 也就是frequency 没有小于0,所以暂时没有多余的这个char on left index. +因此left不能动。这里要测试并且break。 +然而,当frequency < 0时候,说明在后续的String里面出现了多余的char,也就是frequency--使其小于0. 这里,我们就可以动left++了,并且frequency++。 +这个效果就等于,当matched char在后面有重复出现(多余)时,我们可以left++,安全移动。 + +另外. 其余那些不在target里面的char, 用left++过滤掉。 + +3. right pointer一直在按规律跑动。 + +4. 当size == map.size(), 截取string + +*/ +public class Solution { + public String minWindow(String s, String t) { + if (s == null || s.length() == 0 || t == null || t.length() == 0) { + return ""; + } + //Init map based on t + HashMap map = new HashMap(); + for (int i = 0; i < t.length(); i++) { + char c = t.charAt(i); + if (!map.containsKey(c)) { + map.put(c, 0); + } + map.put(c, map.get(c) + 1); + } + + int count = 0; + int start = 0; + int end = 0; + int lengS = s.length(); + int leng = Integer.MAX_VALUE; + String rst = ""; + //Iteratve through s + for (; end < lengS; end++) { + char c = s.charAt(end); + if (map.containsKey(c)) { + map.put(c, map.get(c) - 1); + if (map.get(c) == 0) { + count++; + } + } + + while (start < lengS) { + char cs = s.charAt(start); + if (map.containsKey(cs)) { + //If >= 0 still being used in map, not ready yet: can't move + if (map.get(cs) >= 0) { + break; + } else {//less than 0, so we can skip previous cs, move start++ + map.put(cs, map.get(cs) + 1); + } + } + //skip non-t chars + start++; + } + + if (count == map.size() && (end - start + 1) < leng) { + rst = s.substring(start, end + 1); + leng = rst.length(); + } + }//end for + + return rst; + } +} + + +/* +Same as below solution, incorrect: only picks the first possible solution, not minimum window. +HOWEVER, it accidentally passed LintCode. + +只能找到第一个, 所以有错。 + +//HashT +//HashS: count the frequency of chars from source. +//once found one candidate, we may have a large window. Now move left-most char by comparison using HashS, to minimize the window + +*/ +public class Solution { + public String minWindow(String s, String t) { + if (s == null || s.length() == 0 || t == null || t.length() == 0) { + return ""; + } + + HashMap hashT = new HashMap(); + HashMap hashS = new HashMap(); + //init hashT + for (int i = 0; i < t.length(); i++) { + char c = t.charAt(i); + if (!hashT.containsKey(c)) { + hashT.put(c, 0); + } + hashT.put(c, hashT.get(c) + 1); + } + + //Check against S + int count = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (!hashT.containsKey(c)) { + continue; + } + if (!hashS.containsKey(c)) { + hashS.put(c, 0); + } + hashS.put(c, hashS.get(c) + 1); + + if (hashS.get(c) <= hashT.get(c)) { + count++; + } + + //Found string + if (count == t.length()) { + return findStr(i, s, hashT, hashS); + } + } + return ""; + } + + public String findStr(int end, String s, + HashMap hashT, HashMap hashS) { + int start = 0; + while (start < s.length()) { + char c = s.charAt(start); + if (!hashS.containsKey(c)) { + start++; + continue; + } + if (hashS.get(c) > hashT.get(c)) { + hashS.put(c, hashS.get(c) - 1); + start++; + continue; + } + break; + }//end while + + return s.substring(start, end + 1); + } +} + + + + +/* +Not working: it only picks up the first possible solution, but not the shortest Thoughts: The idea was from jiuzhang.com. 1. count target Characters: store each Character with HashMap:tCounter @@ -38,12 +210,7 @@ srouce string and can also be used as head of the result string (with shorter le import java.util.*; public class Solution { - /** - * @param source: A string - * @param target: A string - * @return: A string denote the minimum window - * Return "" if there is no such a string - */ + public String minWindow(String source, String target) { if (source == null || source.length() == 0) { return source; @@ -110,3 +277,6 @@ public static void main(String[] args) { System.out.println("resutl is : " + rst); } } + + +``` \ No newline at end of file diff --git a/Java/MinimumDepthOfBinaryTree.java b/Java/MinimumDepthOfBinaryTree.java index d5a063f..cf4a2ed 100644 --- a/Java/MinimumDepthOfBinaryTree.java +++ b/Java/MinimumDepthOfBinaryTree.java @@ -1,3 +1,8 @@ +E + +Divide and Conquery一个最小值. 注意处理Leaf的null, 用Integer.MAX_VALUE代替,这样可以避免错误counting. + +``` /* Given a binary tree, find its minimum depth. @@ -62,3 +67,5 @@ public int getMin(TreeNode root) { } } + +``` \ No newline at end of file diff --git a/Java/Missing Ranges.java b/Java/Missing Ranges.java new file mode 100644 index 0000000..c0620b6 --- /dev/null +++ b/Java/Missing Ranges.java @@ -0,0 +1,69 @@ +精力旺盛症。 +自己做的时候,想的太复杂,做起了binarysearch,企图节省时间。 +下次要算清楚,是否有意义。 +binarySearch的确logn,但是在lower 和upper之间的数字,很可能还是O(n). +因此一开始就for一遍也是O(n), 而code会相对来说简单许多。 + +想法: +两个pointer, 每次计较prev和curr之间的部分。 +然后prev = curr,向前移动一格。 + +``` +/* +Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges. + +For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. + +Tags: Array +Similar Problems: (E) Summary Ranges + + +*/ +/* + +Attempt2, Thoughts: +Use two pointer to mark the prev and curr value, then verify the range in between. + +matching conditoin: prev +2 >= curr. +That is, +1,...,3 + +1. When print range: print the missing [x,y] +2. missing x = prev+1, missing y = curr - 1; +3. Make sure prev represents the consecutive integer before missing x. +*/ + +public class Solution { + public List findMissingRanges(int[] nums, int lower, int upper) { + List rst = new ArrayList(); + if (nums == null || nums.length == 0) {//Though, also covered in the for + rst.add(printRange(lower, upper)); + return rst; + } else if (lower > upper) { + return rst; + } + int prev = lower - 1; + int curr; + for (int i = 0; i <= nums.length; i++) { + curr = (i == nums.length) ? upper + 1 : nums[i]; + if (prev + 2 <= curr) { + rst.add(printRange(prev + 1, curr - 1)); + } + prev = curr; + } + return rst; + } + + public String printRange(int from, int to) { + return (from == to) ? String.valueOf(from) : from + "->" + to; + } +} + + +/* +Old solution: attempted to do binary search for lower and upper, then calculate the mid range. O(logn) + O(upper - lower) = O(n) + +Therefore, don't have to do that; just do a run through. + +*/ +``` \ No newline at end of file diff --git a/Java/Multiply Strings.java b/Java/Multiply Strings.java new file mode 100644 index 0000000..86b6433 --- /dev/null +++ b/Java/Multiply Strings.java @@ -0,0 +1,100 @@ +M + +想法不难。turn into int[], 然后每个位子乘积,然后余数carrier移位。 + +但是做起来有很多坑。适合面试黑。 + +1. 数字‘123’, 在数组里面, index == 0 是 ‘1’。 但是我们平时习惯从最小位数开始乘积,就是末尾的'3'开始。 + 所以!翻转两个数字先!我去。这个是个大坑。 + +2. 乘积product,和移动Carrier都很普通。 + +3. !!最后不能忘了再翻转。 + +4. 最后一个看坑。要是乘积是0,就返回‘0’。 但是这个其实可以在开头catch到没必要做到结尾catch。 + +用到几个StringBuffer的好东西: +reverse(); +sb.deleteCharAt(i) + +找数字,或者26个字母,都可以: +s.charAt(i) - '0'; //数字 +s.charAt(i) - 'a'; //字母 + +``` +/* +Given two numbers represented as strings, return multiplication of the numbers as a string. + +Note: The numbers can be arbitrarily large and are non-negative. + +Hide Company Tags Facebook +Hide Tags Math String +Hide Similar Problems (M) Add Two Numbers (E) Plus One (E) Add Binary + +*/ +/* + Thoughts: + 1. too long to multiply int. so convert to int[] + 2. Multiply by definition: + a. create a product[] of num1.size() + num2.size() - 1 + b. catches each product[i + j] + 3. for loop on product array again, to carry over the carries + + if both null, return null. + if both "", return "" + + O(m + n) +*/ +public class Solution { + public String multiply(String num1, String num2) { + if (num1 == null || num2 == null) { + return ""; + } else if (num1.length() == 0 || num2.length() == 0) { + return num1.length() == 0 ? num2 : num1; + } else if (num1.equals("0") || num2.equals("0")) { + return "0"; + } + //reverse string, so to calculate from 0 base. easier to calculate + num1 = new StringBuffer(num1).reverse().toString(); + num2 = new StringBuffer(num2).reverse().toString(); + + //product array. extra leading space for carriers + //normally just need num1.length() + num2.length() -1 + int[] product = new int[num1.length() + num2.length()]; + + //Calculate the product normally + for (int i = 0; i < num1.length(); i++) { + int a = num1.charAt(i) - '0'; + for (int j = 0; j < num2.length(); j++) { + int b = num2.charAt(j) - '0'; + product[i + j] += a * b; + } + } + + //calcualte and output + //remember, now the string is reversed calculated. + //so every time, add to index 0. so it will all reverse back; OR, append, and reverse later. + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < product.length; i++) { + int number = product[i] % 10; + int carrier = product[i] / 10; + sb.append(number); + if (i < product.length - 1) { + product[i + 1] += carrier; + } + } + sb.reverse(); + //trim leading 0's + while (sb.length() > 0 && sb.charAt(0) == '0') { + sb.deleteCharAt(0); + } + + return sb.toString(); + } +} + + + + + +``` \ No newline at end of file diff --git a/Java/Next Permutation.java b/Java/Next Permutation.java old mode 100644 new mode 100755 index 3d4c64c..a851601 --- a/Java/Next Permutation.java +++ b/Java/Next Permutation.java @@ -1,9 +1,24 @@ +M + +需斟酌。 + +Permutation的规律: +1. 从小的数字开始变化因为都是从小的数字开始recursive遍历。 +2. 正因为1的规律,所以找大的断点数字要从末尾开始: 确保swap过后的permutation依然是 前缀固定时 当下最小的。 + +steps: +1. 找到最后一个上升点,k +2. 从后往前,找到第一个比k大的点, bigIndex +3. swap k && bigIndex +4. 最后反转 (k+1,end) + + +``` /* Given a list of integers, which denote a permutation. Find the next permutation in ascending order. -Have you met this question in a real interview? Yes Example For [1,3,2,3], the next permutation is [1,3,3,2] @@ -15,6 +30,12 @@ Tags Expand LintCode Copyright Permutation + +*/ + +/* +http://fisherlei.blogspot.com/2012/12/leetcode-next-permutation.html?_sm_au_=isV7p50vt5RqMQ1Q + Thoughts: Not much info are given. Need to ask. It looks like: We are dong permutation on the given numbers, and find out what's next permutation array based on given order. @@ -25,55 +46,52 @@ To find the next smallest permutation. 1. Find the last increasing index (a peek before decresing): k 2. Find the first bigger permutation: Well, it turns out this first bigger index is always on right side of k. - Note: we are trying to get the least significant change on the given permuation. - Next Step: reverse (k+1, end). This is because: before the change, right side of K will be the largest possible combination. After swapping K, we need the right side to be the smallest combination. (Well, this is my understanding....Still a bit confused on why we take these steps in this problem) + Note: we are trying to get the least significant change on the given permuation. + Next Step: reverse (k+1, end). This is because: before the change, right side of K will be the largest possible combination. + After swapping K, we need the right side to be the smallest combination. (Well, this is my understanding.... + Still a bit confused on why we take these steps in this problem) */ - public class Solution { - /** - * @param nums: an array of integers - * @return: return nothing (void), do not return anything, modify nums in-place instead - */ //Revers the given part of a int[] public int[] reverse(int start, int end, int[] nums) { - for (int i = start, j = end; i < j; i++,j--) { - int temp = nums[i]; - nums[i] = nums[j]; - nums[j] = temp; - } - return nums; + for (int i = start, j = end; i < j; i++,j--) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + return nums; } public int[] nextPermutation(int[] nums) { - if (nums == null || nums.length == 0) { - return nums; - } - //Find last increasing point before decreasing. nums[k] < nums[k+1] - int k = -1; - for (int i = nums.length - 2; i >= 0; i--) { - if (nums[i] < nums[i + 1]) { - k = i; - break; - } - } - if (k == -1) { - return reverse(0, nums.length - 1, nums); - } - //Find first bigger point, from right to left - int bigIndex = -1; - for (int i = nums.length - 1; i >= 0; i--) { - if (nums[i] > nums[k]) { - bigIndex = i; - break; - } - } - //1. Swap bigger index with k; 2. Reverse the right side of k. [Try to make the smallest next permutation] - int temp = nums[k]; - nums[k] = nums[bigIndex]; - nums[bigIndex] = temp; - - return reverse(k + 1, nums.length - 1, nums); + if (nums == null || nums.length == 0) { + return nums; + } + //Find last increasing point before decreasing. nums[k] < nums[k+1] + int k = -1; + for (int i = nums.length - 2; i >= 0; i--) { + if (nums[i] < nums[i + 1]) { + k = i; + break; + } + } + if (k == -1) { + return reverse(0, nums.length - 1, nums); + } + //Find first bigger point, from right to left + int bigIndex = -1; + for (int i = nums.length - 1; i >= 0; i--) { + if (nums[i] > nums[k]) { + bigIndex = i; + break; + } + } + //1. Swap bigger index with k; 2. Reverse the right side of k. [Try to make the smallest next permutation] + int temp = nums[k]; + nums[k] = nums[bigIndex]; + nums[bigIndex] = temp; + + return reverse(k + 1, nums.length - 1, nums); } @@ -81,7 +99,4 @@ public int[] nextPermutation(int[] nums) { } - - - - +``` \ No newline at end of file diff --git a/Java/Nim Game.java b/Java/Nim Game.java new file mode 100644 index 0000000..11866ab --- /dev/null +++ b/Java/Nim Game.java @@ -0,0 +1,45 @@ +著名Nim游戏。 +写一些,发现n=4,5,6,7,8...etc之后的情况有规律性。 +最终很简单n%4!=0就可以了 +``` +/* +You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones. + +Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap. + +For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend. + +Hint: + +If there are 5 stones in the heap, could you figure out a way to remove the stones such that you will always be the winner? + + +Hide Similar Problems (M) Flip Game II + +*/ + + +/* + Thoughts: + If n = 4, we can do the following: + 1 0 0 0 + 1 1 0 0 + 1 1 1 0 + But we'll fail. + + n = 5, we pick 1, 2nd player gets n = 4. + n = 6, we pick 2, 2nd player gets n = 4. + n = 7, we pick 3, 2nd player gets n = 4. + n = 8, regarless whatever we pick, the opponent can make 1st gets n = 4, we fail. + ... + ... + whenever n % 4 = 0, 1st player fail. + +*/ + +public class Solution { + public boolean canWinNim(int n) { + return n % 4 != 0; + } +} +``` \ No newline at end of file diff --git a/Java/Number of Airplane in the sky.java b/Java/Number of Airplane in the sky.java index 32ffe56..963813e 100644 --- a/Java/Number of Airplane in the sky.java +++ b/Java/Number of Airplane in the sky.java @@ -1,3 +1,18 @@ +M + +把Interval拆分成数轴上的Point: +起飞mark 1 +降落mark -1 +用PriorityQueue排序, loop through queue, 计算(起飞+降落)值可能有的max。 + +注意: +同时起飞和降落,就是 1 - 1 = 0. 所以在while loop里面有第二个while loop, +当坐标x重合时,在这里做完所有x点的加减,然后再比较 max。 +这避免了错误多count,或者少count + +``` + + /* http://www.lintcode.com/en/problem/number-of-airplanes-in-the-sky/ Given an interval list which are flying and landing time of the flight. How many airplanes are on the sky at most? @@ -30,43 +45,42 @@ */ class Solution { - class Point { - int x; - int flag; - public Point(int x, int flag) { - this.x = x; - this.flag = flag; - } - } - /** - * @param intervals: An interval array - * @return: Count of airplanes are in the sky. - */ + class Point { + int x; + int flag; + public Point(int x, int flag) { + this.x = x; + this.flag = flag; + } + } + public int countOfAirplanes(List airplanes) { - if (airplanes == null || airplanes.size() == 0) { - return 0; - } - PriorityQueue queue = new PriorityQueue(10, - new Comparator(){ - public int compare(Point a, Point b) { - return a.x - b.x; - } - }); - for (Interval interval : airplanes) { - queue.offer(new Point(interval.start, 1)); - queue.offer(new Point(interval.end, -1)); - } - int count = 0; - int max = 0; - while (!queue.isEmpty()) { - Point p = queue.poll(); - count+= p.flag; - while (!queue.isEmpty() && queue.peek().x == p.x) { - p = queue.poll(); - count += p.flag; - } - max = Math.max(count, max); - } - return max; + if (airplanes == null || airplanes.size() == 0) { + return 0; + } + PriorityQueue queue = new PriorityQueue(10, + new Comparator(){ + public int compare(Point a, Point b) { + return a.x - b.x; + } + }); + for (Interval interval : airplanes) { + queue.offer(new Point(interval.start, 1)); + queue.offer(new Point(interval.end, -1)); + } + int count = 0; + int max = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count+= p.flag; + while (!queue.isEmpty() && queue.peek().x == p.x) {//It handles the case of fly&&land @ same time. Which result in 1 -1 = 0. + p = queue.poll(); + count += p.flag; + } + max = Math.max(count, max); + } + return max; } } + +``` \ No newline at end of file diff --git a/Java/Number of Islands II.java b/Java/Number of Islands II.java index 04bf01a..45fb31d 100644 --- a/Java/Number of Islands II.java +++ b/Java/Number of Islands II.java @@ -1,7 +1,21 @@ +H + +用HashMap的Union-find. + +把board转换成1D array, 就可以用union-find来判断了。 判断时,是在四个方向各走一步,判断是否是同一个Land. + +每走一次operator,都会count++. 若发现是同一个island, count-- + +``` /* -Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator. +Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). +Originally, the 2D matrix is all 0 which means there is only sea in the matrix. +The list pair has k operator and each operator has two integer A[i].x, A[i].y means +that you can change the grid matrix[A[i].x][A[i].y] from sea to island. + +Return how many island are there in the matrix after each operator. + -Have you met this question in a real interview? Yes Example Given n = 3, m = 3, array of pair A = [(0,0),(0,1),(2,2),(2,1)]. @@ -108,3 +122,5 @@ public List numIslands2(int n, int m, Point[] operators) { return rst; } } + +``` \ No newline at end of file diff --git a/Java/Number of Islands.java b/Java/Number of Islands.java index 4aeb36d..a4df355 100644 --- a/Java/Number of Islands.java +++ b/Java/Number of Islands.java @@ -1,9 +1,13 @@ +M + +方法1: 两个for loop brutle force。 DFS把每个跟1相关的都Mark一遍.生成一个island. + +方法2: (暂时没有写union-find的解) 可以用union-find, 就像Number of island II 一样。 只不过这个不Return list, 而只是# of islands -可以自己再做一次。 ``` -/* +/*in Given a boolean 2D matrix, find the number of islands. Example @@ -79,4 +83,36 @@ public boolean check(int x, int y, int mark, boolean[][] grid) { return false; } } + + +//from leetcode: +public class Solution { + + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int count = 0; + for(int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + count = mark(i, j, grid)? (count + 1) : count; + } + } + return count; + } + + public boolean mark(int i, int j, char[][] grid) { + if (i >= 0 && i < grid.length && j >= 0 && j < grid[0].length) { + if (grid[i][j] == '1') { + grid[i][j] = 'M'; + mark(i - 1, j, grid); + mark(i + 1, j, grid); + mark(i, j - 1, grid); + mark(i, j + 1, grid); + return true; + } + } + return false; + } +} ``` \ No newline at end of file diff --git a/Java/One Edit Distance.java b/Java/One Edit Distance.java new file mode 100644 index 0000000..4fbb1d4 --- /dev/null +++ b/Java/One Edit Distance.java @@ -0,0 +1,82 @@ +M + +理解Edit: 就是删除,增加,和替换。 +换完之后,理论上换成的String 就应该全等 +一旦找到不一样的char, 就判断那三种可能性 + +``` +/* +Given two strings S and T, determine if they are both one edit distance apart. + +Hide Company Tags Uber Facebook +Hide Tags String +Hide Similar Problems (H) Edit Distance + +*/ + +/*Recap 3.7.2016 +edit: insert, remove, replace. edit once and they will be same string. +*/ +public class Solution { + public boolean isOneEditDistance(String s, String t) { + if (s == null || t == null || s.equals(t) || Math.abs(s.length() - t.length()) > 1) { + return false; + } + int size = s.length() > t.length() ? t.length() : s.length(); + + for (int i = 0; i < size; i++) { + if (t.charAt(i) != s.charAt(i)) { + //check delete and insert + if (t.substring(i + 1).equals(s.substring(i)) || t.substring(i).equals(s.substring(i + 1))) { + return true; + } + //check replace + return t.substring(i + 1).equals(s.substring(i + 1)); + } + } + return true; + } +} + +/* + Thoughts: + One edit distance: delete, insert, and substitude. + For loop. Whenever differenct, chech 3 cases and return + + Note: null cannot become "" or "a", so whenever s or t is null, return false; +*/ + +public class Solution { + public boolean isOneEditDistance(String s, String t) { + if (s == null || t == null) { + return false; + } else if (Math.abs(s.length() - t.length()) > 1 || s.equals(t)) { + return false; + } + int leng = s.length() > t.length() ? t.length() : s.length(); + for (int i = 0; i < leng; i++) { + String ss = s; + String tt = t; + if (s.charAt(i) != t.charAt(i)) { + //Check delete + tt = t.substring(i + 1); + ss = s.substring(i); + if (tt.equals(ss)) { + return true; + } + //Check insert + tt = t.substring(i); + ss = s.substring(i + 1); + if (tt.equals(ss)) { + return true; + } + //check substitude + ss = s.substring(0, i) + s.substring(i + 1); + tt = t.substring(0, i) + t.substring(i + 1); + return ss.equals(tt); + } + }//end for + return true; + } +} +``` \ No newline at end of file diff --git a/Java/Paint Fence.java b/Java/Paint Fence.java new file mode 100644 index 0000000..5b707c2 --- /dev/null +++ b/Java/Paint Fence.java @@ -0,0 +1,71 @@ +这题目很有意思. 一开始分析的太复杂, 最后按照这个哥们的想法(http://yuanhsh.iteye.com/blog/2219891) 的来做,反而简单了许多。 +设定T(n)的做法,最后题目化简以后就跟Fibonacci number一样一样的。详细分析如下。 +做完,还是觉得如有神。本来是个Easy题,想不到,就是搞不出。 + +12.13.2015再看了一下: +因为最多2个fence 颜色相同。 +假设i是和 i-1不同,那么结果就是 (k-1)*dp[i - 1] +假设i是何 i-1相同,那么根据条件,i-1和i-2肯定不同。那么所有的结果就是(k-1)*dp[i-2] +加在一起就有了。 +``` +/* +There is a fence with n posts, each post can be painted with one of the k colors. + +You have to paint all the posts such that no more than two adjacent fence posts have the same color. + +Return the total number of ways you can paint the fence. + +Note: +n and k are non-negative integers. + +Tags: Dynamic Programming +Similar Problems: (E) House Robber, (M) House Robber II, (M) Paint House, (H) Paint House II + +*/ + +/* +Thoughts: +Inspiration(http://yuanhsh.iteye.com/blog/2219891) +Consider posts from 1 ~ n. Now we look at last post, marked n: +S(n) means: last 2 fence posts have same color. + Note: S(n) will equal to whatever that's on n-1 position. + Also, just because n and n-1 are same, that means n-2 and n-1 have to be differnet. +SO: +S(n) = D(n - 1) +D(n) means: last 2 fence posts have different color. + Note: for n - 1, and n-2 positions, we have 2 different conditions: + For example: xxy, or wxy, same 2 x's or different w vs. x. +So: +D(n) = (k - 1) * (D(n - 1) + S(n - 1)) + +We can also create T(n) = S(n) + D(n); //T(n) is our totoal results. Will need to return T(n); +Use above equations to figure out T(n) +T(n) = S(n) + D(n) = D(n - 1) + (k - 1) * (D(n - 1) + S(n - 1)) + = D(n - 1) + (k - 1)(T(n - 1)) + = (k - 1) * (D(n - 2) + S(n - 2)) + (k - 1)(T(n - 1)) + = (k - 1)(T(n - 1) + T(n - 2)) + Since n-2 >=1, so n>=3. We need fiture out cases for n = 0,1,2,3 + +Note: +n == 1: just k ways +n == 0: just 0. +k == 0: just 0; +Besides these cases, we are okay. Btw, k does not really matter as long as it's >=1, it can be plugged in. +*/ + +public class Solution { + public int numWays(int n, int k) { + if (n <= 1 || k <= 0) { + return n * k; + } + int[] dp = new int[n + 1]; //index based : 1 + dp[0] = 0; + dp[1] = k; + dp[2] = k + k*(k - 1); + for (int i = 3; i <= n; i++) { + dp[i] = (k - 1) * (dp[i - 1] + dp[i - 2]); + } + return dp[n]; + } +} +``` \ No newline at end of file diff --git a/Java/Palindrome Permutation II.java b/Java/Palindrome Permutation II.java new file mode 100755 index 0000000..3a68ad7 --- /dev/null +++ b/Java/Palindrome Permutation II.java @@ -0,0 +1,139 @@ +M + +permutation的综合题: +1. validate Input 是不是可以做palindromic permutation. 这个就是(Palindrome Permutation I) +2. 顺便存一下permutation string的前半部分和中间的single character(if any) +3. DFS 做unique permutation: given input有duplicate characters。 + +``` +/* +Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form. + +For example: + +Given s = "aabb", return ["abba", "baab"]. + +Given s = "abc", return []. + +Hint: + +If a palindromic permutation exists, we just need to generate the first half of the string. +To generate all distinct permutations of a (half of) string, use a similar approach from: Permutations II or Next Permutation. +Hide Tags Backtracking +Hide Similar Problems (M) Next Permutation (M) Permutations II (E) Palindrome Permutation + +*/ + + +//Validate if can build palindromic, add half of the char, and record the odd char. +//Do permutation on first half +public class Solution { + String halfStr = ""; + String oddStr = ""; + public List generatePalindromes(String s) { + List rst = new ArrayList(); + if (s == null || s.length() == 0) { + return rst; + } + if (!validate(s)) { + return rst; + } + boolean[] visited = new boolean[halfStr.length()]; + permutateUnique(rst, "", visited, halfStr); + + for (int i = 0; i < rst.size(); i++) { + String str = rst.get(i); + StringBuffer sb = new StringBuffer(str); + String reverse = sb.reverse().toString(); + rst.set(i, str + oddStr + reverse); + } + + return rst; + } + + //Validate and return palidrome candidate + public boolean validate(String s) { + int[] map = new int[256]; + for (int i = 0; i < s.length(); i++) { + map[s.charAt(i)]++; + } + char[] arr = new char[s.length() / 2]; + int countOdd = 0; + int ind = 0; + for (int i = 0; i < map.length; i++) { + if (map[i] % 2 != 0) { + countOdd++; + oddStr += (char)i; + } + + map[i] = map[i] / 2; + while (map[i] > 0) { + arr[ind] = (char)i; + map[i]--; + ind++; + } + + if (countOdd > 1) { + return false; + } + } + + Arrays.sort(arr); + halfStr = new String(arr); + return true; + } + + //Permutation with duplicates control: + public void permutateUnique(List rst, String str, boolean[] visited, String s) { + if (str.length() == s.length()) { + rst.add(str); + return; + } + for (int i = 0; i < s.length(); i++) { + if (visited[i] || (i > 0 && !visited[i - 1] && s.charAt(i - 1) == s.charAt(i))) { + continue; + } + visited[i] = true; + permutateUnique(rst, str + s.charAt(i), visited, s); + visited[i] = false; + } + } + + + /* + //validation using StringBuffer + public boolean validate(String s) { + int[] map = new int[256]; + for (int i = 0; i < s.length(); i++) { + map[s.charAt(i)]++; + } + StringBuffer sb = new StringBuffer(); + int countOdd = 0; + for (int i = 0; i < map.length; i++) { + if (map[i] % 2 != 0) { + countOdd++; + oddStr += (char)i; + } + + map[i] = map[i] / 2; + while (map[i] > 0) { + sb.append((char)i); + map[i]--; + } + + if (countOdd > 1) { + return false; + } + + } + halfStr = sb.toString(); + char[] arr = halfStr.toCharArray(); + Arrays.sort(arr); + + halfStr = new String(arr); + return true; + } + */ + +} +``` \ No newline at end of file diff --git a/Java/Palindrome Permutation.java b/Java/Palindrome Permutation.java new file mode 100755 index 0000000..7356d7a --- /dev/null +++ b/Java/Palindrome Permutation.java @@ -0,0 +1,117 @@ +E + +注意,条件里面没说是否全是lower case letter + +``` +/* +Given a string, determine if a permutation of the string could form a palindrome. + +For example, +"code" -> False, "aab" -> True, "carerac" -> True. + +Hint: + +Consider the palindromes of odd vs even length. What difference do you notice? +Count the frequency of each character. +If each character occurs even number of times, then it must be a palindrome. How about character which occurs odd number of times? + +Tags: Hash Table +Similar Problems: (M) Longest Palindromic Substring, (E) Valid Anagram, (M) Palindrome Permutation II + +*/ + + +/* +Add each char into map. +Count if odd > 1, false + +Note: Iterate HashMap +HashMap.Entry entry : map.entrySet() +*/ + +public class Solution { + public boolean canPermutePalindrome(String s) { + if (s == null || s.length() == 0) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + String str = s.charAt(i) + ""; + if (!map.containsKey(str)) { + map.put(str, 1); + } else { + map.put(str, map.get(str) + 1); + } + }//ENd for + int countOdd = 0; + for (HashMap.Entry entry : map.entrySet()) { + if (entry.getValue() % 2 == 1) { + countOdd++; + } + if (countOdd > 1) { + return false; + } + }//END for + return true; + } +} + +//LeetCode. Made assumption on ASCII code, so use int[256] +public class Solution { + public boolean canPermutePalindrome(String s) { + if (s == null || s.length() == 0) { + return false; + } + + int[] map = new int[256]; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + map[c] += 1; + } + int countOdd = 0; + for (int i = 0; i < map.length; i++) { + if (map[i] % 2 == 1) { + countOdd++; + } + if (countOdd > 1) { + return false; + } + } + return true; + } +} + +/* +Invalid solution. Assumption made on lowercase letter. +12.12.2015 recap: +use a array of length == 26 to track it? No, because ther ecould be captalized letters, other ASCII code +If with assmption of 26 chars + +AND NO, cannot make that assuption. +*/ +public class Solution { + public boolean canPermutePalindrome(String s) { + if (s == null || s.length() <= 1) { + return true; + } + int[] counts = new int[26]; + for (char c : s.toCharArray()) { + counts[c - 'a'] += 1; + } + int countOne = 0; + for (int count : counts) { + if (count == 1 && countOne >= 1) { + return false; + } else if (count == 1) { + countOne++; + } else if (count % 2 != 0) { + return false; + } + } + + return true; + } +} + + +``` \ No newline at end of file diff --git a/Java/Pascal's Triangle II.java b/Java/Pascal's Triangle II.java new file mode 100644 index 0000000..4ec942f --- /dev/null +++ b/Java/Pascal's Triangle II.java @@ -0,0 +1,59 @@ +E + +简单处理array list. + +``` + + +/* +Given an index k, return the kth row of the Pascal's triangle. + +For example, given k = 3, +Return [1,3,3,1]. + +Note: +Could you optimize your algorithm to use only O(k) extra space? + +Hide Tags Array +Hide Similar Problems (E) Pascal's Triangle + +*/ + + +/* + 1 + 1 1 +1 2 1 +1 3 3 1 +*/ + +//list store 0 1 0. Iteratve over k, each time createa a new list. +//Add 1 on two size before calculating each row +public class Solution { + public List getRow(int rowIndex) { + List rst = new ArrayList(); + if (rowIndex < 0) { + return rst; + } else if (rowIndex == 0) { + rst.add(1); + return rst; + } + + rst.add(1); + ArrayList list = new ArrayList(); + + while (rowIndex > 0) {//2, 1, 0x + list.add(1); + for (int i = 0; i < rst.size() - 1; i++) { + list.add(rst.get(i) + rst.get(i + 1)); + } + list.add(1); + rst = list;//[1,1], [1,2,1] + list = new ArrayList(); + rowIndex--; + } + + return rst; + } +} +``` \ No newline at end of file diff --git a/Java/Peeking Iterator.java b/Java/Peeking Iterator.java new file mode 100644 index 0000000..8c92076 --- /dev/null +++ b/Java/Peeking Iterator.java @@ -0,0 +1,141 @@ +再一次理解错题意. peek() 就是头顶,但是不一定是最大值啊。总是把PEEK想成了最大值,然后用2 STACK做了最大值的cache,练的一手好双stack,可惜错了。 + +回到原题,其实不难。找一个cache来存next()的值,然后每次next()里面维护这个cache就好。 + +``` +/* +Given an Iterator class interface with methods: next() and hasNext(), design and implement a PeekingIterator that support the peek() operation -- it essentially peek() at the element that will be returned by the next call to next(). + +Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3]. + +Call next() gets you 1, the first element in the list. + +Now you call peek() and it returns 2, the next element. Calling next() after that still return 2. + +You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false. + +Hint: + +Think of "looking ahead". You want to cache the next element. +Is one variable sufficient? Why or why not? +Test your design with call order of peek() before next() vs next() before peek(). +For a clean implementation, check out Google's guava library source code. (https://github.com/google/guava/blob/703ef758b8621cfbab16814f01ddcc5324bdea33/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java#L1125) +Follow up: How would you extend your design to be generic and work with all types, not just integer? + +It looks like the guava library uses 'E' for generic element + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Flatten 2D Vector, (M) Zigzag Iterator + +*/ + +/* +Second attempt. +Thoughts: Of coruse can't store in a queue, that will be brutle and meaning less. +Instead, use a iterator variable, cache, to hold next(). +When called next(), move forward; otherwise, return the cache. +Make sure also return the cached peek, and update cache with next() value. +*/ +// Java Iterator interface reference: +// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html +class PeekingIterator implements Iterator { + private int cache; + private Iterator itt; + private boolean notEnd; + public PeekingIterator(Iterator iterator) { + // initialize any member here. + itt = iterator; + cache = itt.next(); + notEnd = iterator.hasNext(); + } + + // Returns the next element in the iteration without advancing the iterator. + public Integer peek() { + return cache; + } + + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + @Override + public Integer next() { + int curr = cache; + notEnd = itt.hasNext(); + if (itt.hasNext()) { + cache = itt.next(); + } + return curr; + } + + @Override + public boolean hasNext() { + return notEnd; + } +} + + + + +/* +Attempt1, failed. Reason: I thought we are looking for the real max-peek element! However, this problem only asks for peek() element, which is not necessarily the maximun element. This mistake is bloody. +Thoughts: +To find peek, have to run through the iterator at least once. O(n). +Store everything in 2 stacks: +We want to process the end of the iterator first, put everything into stack. +Therefore the top of the stack is the next() element of iterator. +Also, use second stack to hold max value for each element stage. + +Each stack1 element has a max coresponding element in stack2. For example, [5,9,1,3,6] +s1: 6,3,1,9,5 [5 gets out first] +s2: 6,6,6,9,9 [end 9 gets out first] +*/ + +// Java Iterator interface reference: +// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html +class PeekingIterator implements Iterator { + private Stack s1; + private Stack s2; + private int size; + public PeekingIterator(Iterator iterator) { + // initialize any member here. + s1 = new Stack(); + s2 = new Stack(); + Stack temp = new Stack(); + size = 0; + int max = Integer.MIN_VALUE; + while(iterator.hasNext()) { + temp.push(iterator.next()); + size++; + } + while(!temp.empty()) { + s1.push(temp.peek()); + max = Math.max(max, temp.peek()); + s2.push(max); + temp.pop(); + } + } + + // Returns the next element in the iteration without advancing the iterator. + public Integer peek() { + if (s1.size() > size) { + s1.pop(); + return s2.pop(); + } else { + return s2.peek(); + } + } + + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + + @Override + public Integer next() { + size--; + return s1.pop(); + } + + @Override + public boolean hasNext() { + return !s1.empty(); + } +} +``` \ No newline at end of file diff --git a/Java/Perfect Squares.java b/Java/Perfect Squares.java new file mode 100644 index 0000000..54a9d9a --- /dev/null +++ b/Java/Perfect Squares.java @@ -0,0 +1,86 @@ +一开始没clue.看了一下提示。 + +1. 第一步想到了,从数学角度,可能是从最大的perfect square number开始算起。 +2. 然后想法到了dp, 假设最后一步用了最大的maxSqrNum, 那么就在剩下的 dp[i - maxSqrNum^2] +1 不就好了? +3. 做了,发现有个问题...最后一步选不选maxSqrNum? 比如12就是个例子。 + 然后就根据提示,想到BFS。顺的。 把1~maxSqrNum 都试一试。找个最小的。 + 看我把12拆分的那个example. 那很形象的就是BFS了。 + 面试时候,如果拆分到这个阶段不确定,那跟面试官陶瓷一下,说不定也就提示BFS了。 +``` +/* +Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. + +For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9. + +Credits: +Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Dynamic Programming Breadth-first Search Math +Hide Similar Problems (E) Count Primes (M) Ugly Number II + +*/ +/* +Thoughts: + Math: + num =13. sqrt(13) = 3.xxx. Floor() = 3. count++;//1 + num = 13 - 9 = 4. sqrt(4) = 2. No remaining. count++;//2 + DP: + state + dp[i]: min # of perfect square till i. + dp[0] = 0; + dp[1] = 1; + dp[2] = 1 + 1 = 2; + dp[3] = 1,1,1;//3 + dp[4] = 2^2;//1 + dp[5] = dp[5 - floor(sqrt(5))^2] + 1; + fn: //Pick the largest perfect square possible, then added on what's remaining's dp. Do a BFS on all possiblilities + maxFlorNum = Math.floor(Math.sqrt(i)) + 12 + -3^2 = 3 -2^2 = 8 -1^2 = 11 + 1 + dp[3] 1 + dp[8] 1 + dp[11] + for (j = 0 ~ i) + dp[i] = min(min, dp[i - j ^ 2] + 1) + init: + dp[0] = 0; + dp[1] = 1; + return dp[n]; +*/ + + + +public class Solution { + public int numSquares(int n) { + if (n <= 0) { + return 0; + } + int[] dp = new int[n + 1]; + dp[0] = 0; + + for (int i = 1; i <= n; i++) { + int maxSqrNum = (int)Math.floor(Math.sqrt(i)); + int min = Integer.MAX_VALUE; + for (int j = 1; j <= maxSqrNum; j++) { + min = Math.min(min, dp[i - j * j] + 1); + } + dp[i] = min; + } + return dp[n]; + } +} + + +/* +//Test Cases + dp[2] =2; + dp[4] = 1 + dp[5] = 2; + dp[6] = 2 + 1 =3; + dp[7] = 3 + 1 = 4; + dp[8] = dp[4] + 1 = 1 = 1 = 2; + dp[9] = 1 + dp[10] = 1 + 1 = 2; + dp[11] = 2 + 1 = 3 + dp[12] = dp[12 - 9] + 3 +*/ +``` \ No newline at end of file diff --git a/Java/Permutation Index.java b/Java/Permutation Index.java old mode 100644 new mode 100755 index 0b67a44..58d222c --- a/Java/Permutation Index.java +++ b/Java/Permutation Index.java @@ -1,39 +1,43 @@ -这题目标为简单。但是做了很久。 -最后分析出来: -每个数位的数字,都是基于这个数字之前越过的战壕...好吧,意思是,跳过了多少种可能。 -对,就用4,2,1举例。网上大家都用这个例子。不行,我要换一个。 +E -换【6,5,2】吧。我们找6,5,2是permudation里面的第几个。 -正常排序,也就是permutation的第一个,应该是【2,5,6】 -如果要从首位,2,变成6,要跨过多少条尸体呢? -很简单,高中就学过,重点来了:小于6的数字有多少个呢?(2,5).然后每个数字变成head,都有各自的变化可能,而每个数字打头,都有(n-1)!种可能。明显了吧,把每个(n-1)!加起来。 注意(n-1)意思就是出去开头的数字(2、5),后面有多少个,有序排列一下有多少情况,不就是(n-1)!嘛。 - 这一步,公式推出来就是很简单的 (有几个小于6的数字呀) ×(出去head剩下有多少个数字)! +和Permutation Sequence相反的题目。思想类似。 -以上 种种,都是为了把6推上皇位,而牺牲的条数。 +题目为Easy,琢磨很久,分析: +每个数位的数字,都是跳过了小于这数字开头的多种可能。 + +举例【6,5,2】吧。我们找6,5,2是permudation里面的第几个。 +正常排序,也就是permutation的第一个,应该是【2,5,6】 +如果要从首位,2,变成6,要跨过多少可能性呢? +很简单,就是问:小于6的数字有多少个呢?(2,5).每个数字变成head,都有各自的一套变化,都有(n-1)!种可能。 + +本题做法:每个(n-1)!加起来。 Note:(n-1) means, 开头的数字(2,5)各带出多少种排列,也就是不就是(n-1)!嘛。 + 这一步,计算数量很简单: (有几个小于6的数字) ×(除去head剩下有多少个数字)! + +以上 ,都是为了把6推上皇位,而牺牲的条数。 那么把6推上去以后,还有接下去的呢。 -接下去要看5,2. +接下去要看5,2. 6确定,后面permudation可变的情况有可能是【6,5,2】,那还可能是【6,2,5】呢。 -方法一样了。 -看given 数组的第二位5,算它接下去: -1. 有几个数字小于5呢? -2. 除去5,还有几个数字可以 factorial呢? -3. 一样的。第一步就结果乘以第二步。 +Same process, 看given 数组的第二位5,算它接下去: +1. 有几个数字小于5呢? +2. 除去5,还有几个数字可以 factorial呢? +3. 一样的。第一步就结果乘以第二步。 -接下去要看最后一个元素2了。 -一样的想法。 +最后接下去要看最后一个元素2了。 -6,5,2全看过了以后咋办。 -加起来呗。 -加起来,就是【6,5,2】上位,所踏过的所有小命啊! +6,5,2全看过了以后,加起来。 +就是【6,5,2】上位,所踏过的所有小命啊! 我这解释太生动了。因为耗费了好长时间思考... + ``` /* -Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. +Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, +which are ordered in lexicographical order. The index begins at 1. + Example Given [1,2,4], return 1. diff --git a/Java/Permutation Sequence.java b/Java/Permutation Sequence.java new file mode 100755 index 0000000..a66a138 --- /dev/null +++ b/Java/Permutation Sequence.java @@ -0,0 +1,196 @@ +M + +k是permutation的一个数位。而permutation是有规律的。 + +也就是说,可以根据k的大小来判断每一个数位的字符(从最大数位开始,因为默认factorio从最大数位开始变化)。 + +于是先求出n!, 然后 k/n!就可以推算出当下这一个数位的字符。然后分别把factorio 和 k减小。 + +另外, 用一个boolean[] visited来确保每个数字只出现一次。 + +这个方法比计算出每个permutation要efficient许多。 + + +``` +/* +The set [1,2,3,…,n] contains a total of n! unique permutations. + +By listing and labeling all of the permutations in order, +We get the following sequence (ie, for n = 3): + +"123" +"132" +"213" +"231" +"312" +"321" +Given n and k, return the kth permutation sequence. + +Note: Given n will be between 1 and 9 inclusive. + +Hide Tags Backtracking Math +Hide Similar Problems (M) Next Permutation (M) Permutations + +*/ +/* + Correct solution is to reduce k, and manipulate the sequence + http://www.jiuzhang.com/solutions/permutation-sequence/ + + Thoughts: + k is the sum of possibilities. + Based on attempt1, attempt2, we understand that each digit leads a differnet sets of possibilities. The total is n! + For example, + factorio = # of a paticular set of possibilities, and remain = (k / factorio) means how any sets are there. + If remain == 0, that means factorio has more possibiities than k (factorio > k) so there is nothing changed on 1st + char position. For example, if given [1,2,3], then the string will end up as '1xx'. + + With the above fact, we can find out each char by calculate k vs. factorio. + + Note, each round, the factorio itself need to reduced. +*/ + +public class Solution { + public String getPermutation(int n, int k) { + if (n <= 0 || k <= 0) { + return ""; + } + StringBuffer sb = new StringBuffer(); + boolean[] visited = new boolean[n]; + //Largest possible number of posibilities, n! + int factorio = 1; + for (int i = 1; i < n; i++) { + factorio *= i; + } + //Put k into 0-base + k = k - 1; + + for (int i = 0; i < n; i++) { + int index = k / factorio; + k = k % factorio; + + for (int j = 0; j < n; j++) { + if (!visited[j]) { + if (index == 0) { + visited[j] = true; + sb.append((char)('0' + j + 1)); + break; + } else { + index--; + } + } + } + + if (i < n - 1) { + factorio = factorio / (n - i - 1); + } + } + + return sb.toString(); + } +} + + +/* + Based on attempt1, we can actually find every index in front by calling getPermutation(n,k) recursivly + Still timeout +*/ +public class Solution { + public String getPermutation(int n, int k) { + if (n <= 0 || k <= 0) { + return ""; + } + ArrayList nums = new ArrayList(); + for (int i = 1; i <= n; i++) { + nums.add(i); + } + + int frontInd = 0; + for (; frontInd < nums.size(); frontInd++) { + //find max # of permutations that's less than k, and start permutation with that perticular n at index 0. + int factorio = 1; + for (int i = 1; i < n; i++) { + factorio = factorio * i; + } + int startInd = frontInd; + int numPermute = factorio; + while (numPermute < k) { + numPermute += factorio; + startInd++; + } + + if (startInd != frontInd) { + int temp = nums.get(startInd); + nums.remove(startInd); + nums.add(frontInd, temp); + k = k - numPermute; + n--; + } + } + StringBuffer sb = new StringBuffer(); + for (int num : nums) { + sb.append(num); + } + return sb.toString(); + } +} + +/* + Attempt1: timeout + based on k[1 ~ k], find the max x that has x! < k, where x = [1 ~ n] + then swap (x + 1) and 1, start permutation, and find the (k - x!)th +*/ +public class Solution { + public String rst = ""; + public int index = 0; + public String getPermutation(int n, int k) { + if (n <= 0 || k <= 0) { + return ""; + } + int[] nums = new int[n]; + for (int i = 0; i < nums.length; i++) { + nums[i] = i + 1; + } + + //find max # of permutations that's less than k, and start permutation with that perticular n at index 0. + int factorio = 1; + for (int i = 1; i < n; i++) { + factorio = factorio * i; + } + int startInd = 0; + int numPermute = factorio; + while (numPermute + factorio < k) { + numPermute += factorio; + startInd++; + } + + if (startInd != 0) { + int temp = nums[startInd];//findMax return value in [1 ~ n], and we need index + nums[startInd] = nums[0]; + nums[0] = temp; + + k = k - numPermute; + } + + permute("", k, nums);// startInd + 1 is in [1 ~ n] + return rst; + } + + public void permute(String s, int k, int[] nums) { + if (rst.length() != 0) { + return; + } + if (s.length() == nums.length) { + index++; + if (index == k) { + rst = s; + } + return; + } + for (int i = 0; i < nums.length; i++) { + if (!s.contains(nums[i] + "")) { + permute(s + nums[i], k, nums); + } + } + } +} +``` \ No newline at end of file diff --git a/Java/Permutations II.java b/Java/Permutations II.java old mode 100644 new mode 100755 index 38a1438..4aa96aa --- a/Java/Permutations II.java +++ b/Java/Permutations II.java @@ -1,5 +1,22 @@ -要unique,就是要确定visit过的那个index不被重新visit. -一个办法就是给一个visited queue。 和queue在所有的地方一同populate. 然后visited里面存得时visited indexes +M + +方法1: +Mark visited. 并且要检查上一层recursive时有没有略过重复element. 并且要排序,通过permutation规律查看是否排出了重复结果。 + +背景1:在recursive call里面有for loop, 每次从i=0开始, 试着在当下list上加上nums里面的每一个。 +从i=0开始,所以会依次recursive每一个nums:因此,例如i=2,肯定比i=3先被访问。也就是:取i=2的那个list permutation肯定先排出来。 + +背景2:重复的例子:给出Input[x, y1, y2], 假设y的值是一样的。那么,{x,y1,y2}和{x,y2,y1}是相同结果。 + +综上,y1肯定比y2先被访问,{x,y1,y2}先出。 紧随其后,在另一个recursive循环里,{x,y2...}y2被先访问,跳过了y1。 +重点:规律在此,如果跳过y1,也就是visited[y1] == false, 而num[y2] == num[y1],那么这就是一个重复的结果,没必要做,越过。 + +结果:那么,我们需要input像{x,y1,y2}这样数值放一起,那么必须排序。 + + +方法2: +一个办法就是给一个visited queue。 和queue在所有的地方一同populate. 然后visited里面存得时visited indexes。 (Not efficient code. check again) + ``` /* Given a list of numbers with duplicate number in it. Find all unique permutations. @@ -25,6 +42,43 @@ */ +/* +3.3.2016 recap, leetcode +Use visited[i] to mark visited copies +*/ +public class Solution { + public List> permuteUnique(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + Arrays.sort(nums); + boolean[] visited = new boolean[nums.length]; + helper(rst, new ArrayList(), nums, visited); + + return rst; + } + + public void helper(List> rst, ArrayList list, int[] nums, boolean[] visited) { + if (list.size() == nums.length) { + rst.add(new ArrayList(list)); + return; + } + + for (int i = 0; i < nums.length; i++) { + if (visited[i] || (i != 0 && visited[i - 1] && nums[i] == nums[i - 1])) { + continue; + } + list.add(nums[i]); + visited[i] = true; + helper(rst, list, nums, visited); + list.remove(list.size() - 1); + visited[i] = false; + + } + } +} + /* Thoughts: @@ -89,10 +143,6 @@ public ArrayList> permuteUnique(ArrayList nums) { Do a backtrack on the dfs, to make sure a element has same chance of 'selectd' or 'non-solectd' */ class Solution { - /** - * @param nums: A list of integers. - * @return: A list of unique permutations. - */ public ArrayList> permuteUnique(ArrayList nums) { ArrayList> rst = new ArrayList>(); if (nums == null || nums.size() == 0) { @@ -127,5 +177,4 @@ public void dfs (ArrayList nums, ArrayList list, - ``` \ No newline at end of file diff --git a/Java/Permutations.java b/Java/Permutations.java old mode 100644 new mode 100755 index 89bfab2..1e03230 --- a/Java/Permutations.java +++ b/Java/Permutations.java @@ -1,5 +1,10 @@ -还是递归: 取,或者不取。 -Iterative: 用个queue,每次poll()出来的list, 把在nums里面能加的挨个加一遍。 +M + +Recursive: 取,或者不取。 + +Iterative: 用个queue,每次poll()出来的list, 把在nums里面能加的挨个加一遍。 However, code is a bit massive. + + ``` /* Given a list of numbers, return all possible permutations. @@ -31,6 +36,68 @@ */ +/* + +Thinking Process: +1. Very similar idea: choose or not choose (1 / 0) + A key point is: when jumpped into next level of recursion, the 'list' will surely be filled up until it reach the max length. + That is: when 'not choose', the empty seat will be filled eventually with points not existed in 'list'. +2. The recursion does not end before the list is filled. +3. A for loop is doiong the filling of blank. Any order/combination will occur. +*/ + +class Solution { + public ArrayList> permute(ArrayList nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.size() == 0) { + return rst; + } + ArrayList list = new ArrayList(); + helper(rst, list, nums); + return rst; + } + + public void helper(ArrayList> rst, ArrayList list, ArrayList nums) { + if (list.size() == nums.size()) { + rst.add(new ArrayList(list)); + return ; + } + for (int i = 0; i < nums.size(); i++) { + if (!list.contains(nums.get(i))) { + list.add(nums.get(i)); + helper(rst, list, nums); + list.remove(list.size() - 1); + } + } + } +} +//Same solution as above, for Leetcode: +public class Solution { + public List> permute(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + helper(rst, new ArrayList(), nums); + return rst; + } + + public void helper(List> rst, ArrayList list, int[] nums) { + if (list.size() == nums.length) { + rst.add(new ArrayList(list)); + } + + for (int i = 0; i < nums.length; i++) { + if (!list.contains(nums[i])) { + list.add(nums[i]); + helper(rst, list, nums); + list.remove(list.size() - 1); + } + } + } +} + + /* Thoughts: 12.07.2015 recap recursive: @@ -48,10 +115,6 @@ */ class Solution { - /** - * @param nums: A list of integers. - * @return: A list of permutations. - */ public ArrayList> permute(ArrayList nums) { ArrayList> rst = new ArrayList>(); if (nums == null || nums.size() == 0) { @@ -86,45 +149,5 @@ public ArrayList> permute(ArrayList nums) { -/* - -Thinking Process: -1. Very similar idea: choose or not choose (1 / 0) - A key point is: when jumpped into next level of recursion, the 'list' will surely be filled up until it reach the max length. - That is: when 'not choose', the empty seat will be filled eventually with points not existed in 'list'. -2. The recursion does not end before the list is filled. -3. A for loop is doiong the filling of blank. Any order/combination will occur. -*/ - -class Solution { - /** - * @param nums: A list of integers. - * @return: A list of permutations. - */ - public ArrayList> permute(ArrayList nums) { - ArrayList> rst = new ArrayList>(); - if (nums == null || nums.size() == 0) { - return rst; - } - ArrayList list = new ArrayList(); - helper(rst, list, nums); - return rst; - } - - public void helper(ArrayList> rst, ArrayList list, ArrayList nums) { - if (list.size() == nums.size()) { - rst.add(new ArrayList(list)); - return ; - } - for (int i = 0; i < nums.size(); i++) { - if (!list.contains(nums.get(i))) { - list.add(nums.get(i)); - helper(rst, list, nums); - list.remove(list.size() - 1); - } - } - } -} - ``` \ No newline at end of file diff --git a/Java/Populating Next Right Pointers in Each Node II.java b/Java/Populating Next Right Pointers in Each Node II.java new file mode 100755 index 0000000..4566580 --- /dev/null +++ b/Java/Populating Next Right Pointers in Each Node II.java @@ -0,0 +1,107 @@ +H + +非perfect tree, 也就是有random的null children. DFS+BFS + + +Populating Next Right Pointers in Each Node I 里面依赖parent.next.left来作链接,但现在这个parent.next.left很可能也是Null. + +1. 于是需要移动parent去找children level的next node。 +2. 并且每次在一个level, 要用BFS的思想把所有parent 过一遍,也就是把parent 正下方的children全部用.next链接起来 + 原因: 到下一层children变成parent, 他们需要彼此之间的connection, grand children才可以相互连接。 + + +Note: runtime O(n * 2^log(n) ) = O(n^2), not good. + +``` +/* +Follow up for problem "Populating Next Right Pointers in Each Node". + +What if the given tree could be any binary tree? Would your previous solution still work? + +Note: + +You may only use constant extra space. +For example, +Given the following binary tree, + 1 + / \ + 2 3 + / \ \ + 4 5 7 +After calling your function, the tree should look like: + 1 -> NULL + / \ + 2 -> 3 -> NULL + / \ \ + 4-> 5 -> 7 -> NULL +Hide Company Tags Microsoft Bloomberg Facebook +Hide Tags Tree Depth-first Search +Hide Similar Problems (M) Populating Next Right Pointers in Each Node + +*/ + +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ + + /* + DFS to traverse the tree. + Also BFS using next pointer. clear node's children level per visit + */ + public class Solution { + public void connect(TreeLinkNode root) { + if (root == null || (root.left == null && root.right == null)) { + return; + } + dfs(root); + } + //Clear connection problems on each level: because the lower children level will relay on parent's level connection. + public void dfs(TreeLinkNode node) { + if (node == null) { + return; + } + TreeLinkNode parent = node; + while (parent != null) { + //Connect left-> right in normal case + if (parent.left != null) { + parent.left.next = parent.right; + } + //Left || right: one of needs to use addRight(node) method to build the .next bridge. + if (parent.left != null && parent.left.next == null) {//Fact: parent.right = null, from last step + parent.left.next = addRight(parent); + } else if (parent.right != null && parent.right.next == null) { + parent.right.next = addRight(parent); + } + parent = parent.next; + } + + dfs(node.left); + dfs(node.right); + } + + //Always take parentNode, and try to return the very first available node at child level + public TreeLinkNode addRight(TreeLinkNode node) { + while (node != null) { + if (node.next == null) { + return null; + } + if (node.next.left != null) { + return node.next.left; + } + if (node.next.right != null) { + return node.next.right; + } + node = node.next; + } + return null; + } + +} + + +``` \ No newline at end of file diff --git a/Java/Populating Next Right Pointers in Each Node.java b/Java/Populating Next Right Pointers in Each Node.java new file mode 100644 index 0000000..28160e1 --- /dev/null +++ b/Java/Populating Next Right Pointers in Each Node.java @@ -0,0 +1,115 @@ +M + +方法1: +题目要求DFS。 +其实basic implementation. 每次处理node.left.next = node.right; node.right.next = node.next.left; + + +方法2: +不和题意,用了queue space,与Input成正比。太大。 + +BFS over Tree。 用Queue 和 queue.size(),老规矩。 +process每层queue时, 注意把next pointer加上去就好. + +``` +/* +Given a binary tree + + struct TreeLinkNode { + TreeLinkNode *left; + TreeLinkNode *right; + TreeLinkNode *next; + } +Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. + +Initially, all next pointers are set to NULL. + +Note: + +You may only use constant extra space. +You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children). +For example, +Given the following perfect binary tree, + 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 +After calling your function, the tree should look like: + 1 -> NULL + / \ + 2 -> 3 -> NULL + / \ / \ + 4->5->6->7 -> NULL +Hide Tags Tree Depth-first Search +Hide Similar Problems (H) Populating Next Right Pointers in Each Node II (M) Binary Tree Right Side View + +*/ + + +/** + * Definition for binary tree with next pointer. + * public class TreeLinkNode { + * int val; + * TreeLinkNode left, right, next; + * TreeLinkNode(int x) { val = x; } + * } + */ + +//DFS. Basic implementation according to problem. + public class Solution { + public void connect(TreeLinkNode root) { + if (root == null || (root.left == null && root.right == null)) { + return; + } + root.left.next = root.right; + dfs(root.left); + dfs(root.right); + } + + public void dfs(TreeLinkNode node) { + if (node == null || node.left == null || node.right == null) { + return; + } + node.left.next = node.right; + if (node.next != null) + node.right.next = node.next.left; + dfs(node.left); + dfs(node.right); + } +} + + + + + //BFS, However, 不和题意。 point each node to the next in queue. if none, add null +public class Solution { + public void connect(TreeLinkNode root) { + if (root == null || (root.left == null && root.right == null)) { + return; + } + Queue queue = new LinkedList(); + queue.offer(root); + int size = 0; + + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + TreeLinkNode node = queue.poll(); + if (i < size - 1) { + node.next = queue.peek(); + } else { + node.next = null; + } + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } + size = queue.size(); + } + } +} +``` \ No newline at end of file diff --git a/Java/Power of Three.java b/Java/Power of Three.java new file mode 100644 index 0000000..25a1534 --- /dev/null +++ b/Java/Power of Three.java @@ -0,0 +1,42 @@ +E + +Power of 3: 3 ^ x == n ? + +做出发. 查%. + +``` +/* + +Given an integer, write a function to determine if it is a power of three. + +Follow up: +Could you do it without using any loop / recursion? + +Credits: +Special thanks to @dietpepsi for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Math +Hide Similar Problems (E) Power of Two + + +*/ + +//Check if n = 3 ^ x; +public class Solution { + public boolean isPowerOfThree(int n) { + if (n <= 0) { + return false; + } + if (n == 1) { + return true; + } + if (n % 3 != 0) { + return false; + } + return isPowerOfThree(n / 3); + } +} + + +``` \ No newline at end of file diff --git a/Java/QuickSort.java b/Java/QuickSort.java index 9f1a879..083c020 100644 --- a/Java/QuickSort.java +++ b/Java/QuickSort.java @@ -1,3 +1,5 @@ +E + 代码是不难的. 首先partition. 返还一个partition的那个中间点的位置。 @@ -8,6 +10,7 @@ 但是: 在partition array那个题目里面,第二个 nums[end] >= pivot, 是要去加上这个 ‘=’的 + ``` /* Quick Sort a array. diff --git a/Java/Rehashing.java b/Java/Rehashing.java old mode 100644 new mode 100755 index 37f69b4..f2fec52 --- a/Java/Rehashing.java +++ b/Java/Rehashing.java @@ -1,5 +1,11 @@ +M + + +``` /* -The size of the hash table is not determinate at the very beginning. If the total size of keys is too large (e.g. size >= capacity / 10), we should double the size of the hash table and rehash every keys. Say you have a hash table looks like below: +The size of the hash table is not determinate at the very beginning. +If the total size of keys is too large (e.g. size >= capacity / 10), +we should double the size of the hash table and rehash every keys. Say you have a hash table looks like below: size=3, capacity=4 @@ -59,56 +65,56 @@ public class Solution { * @return: A list of The first node of linked list which have twice size */ public ListNode[] rehashing(ListNode[] hashTable) { - if (hashTable == null || hashTable.length == 0) { - return hashTable; - } - //Find longest size - /* - int longest = 0; - for (int i = 0; i < hashTable.length; i++) { - ListNode node = hashTable[i]; - int count = 0; - while (node != null) { - count++; - node = node.next; - } - longest = Math.max(longest, count); - }*/ - //Calculate new capacity - //Just to clarify, this problem asks to double the hashtable size, rather than 'longest' times longer. - int capacity = hashTable.length * 2; - if (capacity == hashTable.length) { - return hashTable; - } - - ListNode[] rst = new ListNode[capacity]; - for (int i = 0; i < hashTable.length; i++) { - ListNode node = hashTable[i]; - while (node != null) { - ListNode newNode = new ListNode(node.val); - int hCode = hashcode(newNode.val, capacity); - if (rst[hCode] == null) { - rst[hCode] = newNode; - } else { - ListNode move = rst[hCode]; - while (move.next != null) { - move = move.next; - } - move.next = newNode; - } - node = node.next; - } - } - - return rst; + if (hashTable == null || hashTable.length == 0) { + return hashTable; + } + //Find longest size + /* + int longest = 0; + for (int i = 0; i < hashTable.length; i++) { + ListNode node = hashTable[i]; + int count = 0; + while (node != null) { + count++; + node = node.next; + } + longest = Math.max(longest, count); + }*/ + //Calculate new capacity + //Just to clarify, this problem asks to double the hashtable size, rather than 'longest' times longer. + int capacity = hashTable.length * 2; + if (capacity == hashTable.length) { + return hashTable; + } + + ListNode[] rst = new ListNode[capacity]; + for (int i = 0; i < hashTable.length; i++) { + ListNode node = hashTable[i]; + while (node != null) { + ListNode newNode = new ListNode(node.val); + int hCode = hashcode(newNode.val, capacity); + if (rst[hCode] == null) { + rst[hCode] = newNode; + } else { + ListNode move = rst[hCode]; + while (move.next != null) { + move = move.next; + } + move.next = newNode; + } + node = node.next; + } + } + + return rst; } public int hashcode(int key, int capacity) { - if (key < 0) { - return (key % capacity + capacity) % capacity; - } else { - return key % capacity; - } + if (key < 0) { + return (key % capacity + capacity) % capacity; + } else { + return key % capacity; + } } }; @@ -124,3 +130,5 @@ public int hashcode(int key, int capacity) { + +``` \ No newline at end of file diff --git a/Java/Remove Node in Binary Search Tree.java b/Java/Remove Node in Binary Search Tree.java old mode 100644 new mode 100755 index bffbc98..2617770 --- a/Java/Remove Node in Binary Search Tree.java +++ b/Java/Remove Node in Binary Search Tree.java @@ -1,5 +1,15 @@ +H + +方法1: Brutle一点。找到target和target的parent. +把target remove时,把target的children nodes 重新排列组成新的BST: inorder traversal, build tree based on inorder traversal list. + +方法2: 分析规律,先找到target和parent, 然后根据性质,把target remove时,移动children nodes, 保证还是BST。 + +``` /* -Given a root of Binary Search Tree with unique value for each node. Remove the node with given value. If there is no such a node with given value in the binary search tree, do nothing. You should keep the tree still a binary search tree after removal. +Given a root of Binary Search Tree with unique value for each node. Remove the node with given value. +If there is no such a node with given value in the binary search tree, do nothing. +You should keep the tree still a binary search tree after removal. Example Given binary search tree: @@ -41,6 +51,101 @@ Tags Expand LintCode Copyright Binary Search Tree + +*/ + +//Recap, 2024.2016 +//Find target. Serialize (inorder) target's children. De-serialize the list, without target. +public class Solution { + public TreeNode removeNode(TreeNode root, int value) { + if (root == null) { + return root; + } + //Find target and target.parent + TreeNode parent = findTargetParent(root, value); + TreeNode target; + if (parent == null) { + return root; + } + if (parent.val == value) { + target = parent; + } else if (parent.left != null && parent.left.val == value) { + target = parent.left; + } else { + target = parent.right; + } + + + //Build inorder traversal based on target node. + ArrayList list = new ArrayList(); + inorderTraversal(target, list, target); + + //Build new subtree and attach to original tree + if (parent.val == value) { + return buildBFS(list, 0, list.size() - 1); + } + if (parent.left != null && parent.left.val == value) { + parent.left = buildBFS(list, 0, list.size() - 1); + } else { + parent.right = buildBFS(list, 0, list.size() - 1); + } + + return root; + } + + //Find and return target, where target.val == value + public TreeNode findTargetParent(TreeNode node, int value) { + if (node == null || node.val == value) { + return node; + } + + if (value < node.val) { + if (node.left != null && value == node.left.val) { + return node; + } + return findTargetParent(node.left, value); + } else { + if (node.right != null && value == node.right.val) { + return node; + } + return findTargetParent(node.right, value); + } + } + + //Traverse target's children and build a inorder list + public void inorderTraversal(TreeNode node, ArrayList rst, TreeNode skipNode) { + if (node.left != null) { + inorderTraversal(node.left, rst, skipNode); + } + if (node.val != skipNode.val) { + rst.add(new TreeNode(node.val)); + } + if (node.right != null) { + inorderTraversal(node.right, rst, skipNode); + } + } + + //Build tree based on given inorder-traversal list + public TreeNode buildBFS(ArrayList list, int start, int end) { + if (start < end) { + int mid = start + (end - start)/2; + TreeNode root = list.get(mid); + root.left = buildBFS(list, start, mid - 1); + root.right = buildBFS(list, mid + 1, end); + return root; + } + if (start == end) { + return list.get(start); + } + + return null; + } + +} + + + +/* Thoughts: We can think of a couple different cases: where is that target node to remove? It can be root, a child (a couple more situations) Note: before going futher, remember the technique to rip off parent node. In a binary tree, L > parent > R, so always find the L's right-most node and replace parent. @@ -56,55 +161,55 @@ */ public class Solution { public TreeNode removeNode(TreeNode root, int value) { - if (root == null || (root.left == null && root.right == null)) { - return null; - } - TreeNode dummy = new TreeNode(0);; - dummy.left = root; - //Find node - TreeNode parent = findTargetParent(dummy, root, value); - TreeNode child; - if (parent.left != null && parent.left.val == value) { - child = parent.left; - } else if (parent.right != null && parent.right.val == value) { - child = parent.right; - } else { - return dummy.left; - } - //Delete that node: - deleteTargetNode(parent, child); - return dummy.left; + if (root == null || (root.left == null && root.right == null)) { + return null; + } + TreeNode dummy = new TreeNode(0);; + dummy.left = root; + //Find node + TreeNode parent = findTargetParent(dummy, root, value); + TreeNode child; + if (parent.left != null && parent.left.val == value) { + child = parent.left; + } else if (parent.right != null && parent.right.val == value) { + child = parent.right; + } else { + return dummy.left; + } + //Delete that node: + deleteTargetNode(parent, child); + return dummy.left; } - //Find target node - public TreeNode findTargetParent(TreeNode parent, TreeNode node, int value){ - if (node == null || node.val == value) { - return parent; - } - - if (value < node.val) { - return findTargetParent(node, node.left, value); - } else { - return findTargetParent(node, node.right, value); - } + //Find target node + public TreeNode findTargetParent(TreeNode parent, TreeNode node, int value){ + if (node == null || node.val == value) { + return parent; + } + + if (value < node.val) { + return findTargetParent(node, node.left, value); + } else { + return findTargetParent(node, node.right, value); + } } //Delete node public void deleteTargetNode(TreeNode parent, TreeNode target) { - //Case1 + case2: (target.L == null && target.R == null) || (target.R == null && target.L != null) - if (target.right == null) { - if (parent.left == target) { - parent.left = target.left; - } else { - parent.right = target.left; - } - } else {//Case3: when target.right != null - TreeNode replaceNode = target.right; - TreeNode replaceParent = target; - while(replaceNode.left != null) { - replaceParent = replaceNode; - replaceNode = replaceNode.left; - } + //Case1 + case2: (target.L == null && target.R == null) || (target.R == null && target.L != null) + if (target.right == null) { + if (parent.left == target) { + parent.left = target.left; + } else { + parent.right = target.left; + } + } else {//Case3: when target.right != null + TreeNode replaceNode = target.right; + TreeNode replaceParent = target; + while(replaceNode.left != null) { + replaceParent = replaceNode; + replaceNode = replaceNode.left; + } //Remove replaceNode from replaceParent if (replaceParent.left == replaceNode) {//Usually it'll be replaceParent.left replaceParent.left = replaceNode.right; @@ -119,9 +224,9 @@ public void deleteTargetNode(TreeNode parent, TreeNode target) { parent.right = replaceNode; } - replaceNode.left = target.left; - replaceNode.right = target.right; - } + replaceNode.left = target.left; + replaceNode.right = target.right; + } } } @@ -133,3 +238,5 @@ public void deleteTargetNode(TreeNode parent, TreeNode target) { + +``` \ No newline at end of file diff --git a/Java/Restore IP Addresses.java b/Java/Restore IP Addresses.java new file mode 100644 index 0000000..1d4b809 --- /dev/null +++ b/Java/Restore IP Addresses.java @@ -0,0 +1,89 @@ +递归的终点:list.zie() == 4 +递归在一个index上面(具体问题,具体分析的情况) +validate string要注意leading '0' + +注意: 递归的时候可以用一个start/level/index来跑路 +但是尽量不要去改变Input source, 会变得非常confusing. + +``` +/* + +Given a string containing only digits, restore it by returning all possible valid IP address combinations. + +For example: +Given "25525511135", + +return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) + +Hide Tags Backtracking String + +*/ + +/* + Thoughts: + NOT DONE. NEED CLEAR MIND + Break into 4 parts. + At each index, either close it as one IP spot, or not. + recursive down. + If level == 4 validate if valid IP address. If so, add it. + pass along: rst, list (store the 4 IP spots), level (0 ~ 3), s, + for (0 ~ 2): can pick 1 digit, 2 digits, or 3 digits +*/ +public class Solution { + public List restoreIpAddresses(String s) { + List rst = new ArrayList(); + if (s == null || s.length() == 0) { + return rst; + } + if (s.length() < 4 || s.length() > 12) { + return rst; + } + ArrayList list = new ArrayList(); + helper(rst, list, 0, s); + + return rst; + } + + public void helper(List rst, ArrayListlist, + int start, String s) { + if (list.size() == 4) { + if (start != s.length()) { + return; + } + StringBuffer sb = new StringBuffer(); + for (String str : list) { + sb.append(str + "."); + } + rst.add(sb.substring(0, sb.length() - 1).toString()); + return; + } + //run for loop 3 times: one IP spot has at most 3 digits + for (int i = start; i < s.length() && i <= start + 3; i++) { + String temp = s.substring(start, i + 1); + if (isValid(temp)) { + list.add(temp); + helper(rst, list, i + 1, s); + list.remove(list.size() - 1); + } + } + } + //Valid the IP [0,255]; cannot start with 0 if it's not 0 + public boolean isValid(String str) { + if (str.charAt(0) == '0') { + return str.equals("0"); + } + int num = Integer.parseInt(str); + return num <= 255 && num >= 0; + } + +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Java/Reverse Linked List.java b/Java/Reverse Linked List.java index fde66e4..174b727 100644 --- a/Java/Reverse Linked List.java +++ b/Java/Reverse Linked List.java @@ -1,3 +1,9 @@ +E + +建立新list。每次把newList append 在current node的后面。 +用head来循环所有node。 + +``` /* Reverse a linked list. @@ -12,49 +18,21 @@ Linked List Facebook Uber */ +//Use empty node, add to tail, append empty node to next node. keep going like that public class Solution { - /** - * @param head: The head of linked list. - * @return: The new head of reversed linked list. - */ - public ListNode reverse(ListNode head) { + public ListNode reverseList(ListNode head) { if (head == null || head.next == null) { return head; } - - ListNode dummy = new ListNode(0); - - while (head != null) { - //Take head out - ListNode temp = head; - //Head moves on - head = head.next; - //Cut the dummy list, insert temp in front - temp.next = dummy.next; - dummy.next = temp; - } - - return dummy.next; - } -} + ListNode newList = null; -//This is a more easy to 'apply and go' version. -public class Solution { - /** - * @param head: The head of linked list. - * @return: The new head of reversed linked list. - */ - public ListNode reverse(ListNode head) { - if (head == null) { - return head; - } - ListNode reversedList = null; while (head != null) { - ListNode cutOffPart = head.next; - head.next = reversedList; - reversedList = head; - head = cutOffPart; + ListNode temp = head.next; + head.next = newList; + newList = head; + head = temp; } - return reversedList; + return newList; } -} \ No newline at end of file +} +``` \ No newline at end of file diff --git a/Java/Reverse Words in a String II.java b/Java/Reverse Words in a String II.java new file mode 100644 index 0000000..bb4465c --- /dev/null +++ b/Java/Reverse Words in a String II.java @@ -0,0 +1,112 @@ +M + +In-place reverse. + +reverse用两回. 全局reverse。局部:遇到空格reverse。 + +注意:结尾点即使没有' '也要给reverse一下最后一个词。 + + +``` +/* +Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters. + +The input string does not contain leading or trailing spaces and the words are always separated by a single space. + +For example, +Given s = "the sky is blue", +return "blue is sky the". + +Could you do it in-place without allocating extra space? + +Related problem: Rotate Array + +Hide Company Tags Amazon Microsoft +Hide Tags String +Hide Similar Problems (M) Reverse Words in a String (E) Rotate Array + + +*/ + +/* + Recap: 02.10.2016 + //1. reverse all. 2. reverse local with 2 pointer. + //build reverse(start,end) +*/ + +public class Solution { + public void reverseWords(char[] s) { + if (s == null || s.length <= 1) { + return; + } + reverse(s, 0, s.length - 1); + int start = 0; + for (int i = 0; i < s.length; i++) { + if (s[i] == ' ') { + reverse(s, start, i - 1); + start = i + 1; + } else if (i == s.length - 1) { + reverse(s, start, i); + } + }//end for + } + + public void reverse(char[] s, int start, int end) { + while (start < end) { + char temp = s[start]; + s[start] = s[end]; + s[end] = temp; + start++; + end--; + } + } +} + + +/* +Thoughts: write an example: reverse the whole thing, then reverse each individual word, split by space. + +Note: becase we don't have space at end of the char[], so we will ignore last word. Remember to reverse that one. +*/ +public class Solution { + public void reverseWords(char[] s) { + if (s == null || s.length == 0) { + return; + } + int len = s.length; + //reverse whole + for (int i = 0; i < len / 2; i++) { + char temp = s[i]; + s[i] = s[len - 1 - i]; + s[len - 1 - i] = temp; + } + + //reverse partial + int start = 0; + int mid = 0; + int end = 0; + for (int i = 0; i < len; i++) { + if (s[i] == ' ') { + mid = start + (end - start) / 2; + for (int j = start; j <= mid; j++) { + char temp = s[j]; + s[j] = s[end - (j - start)]; + s[end - (j - start)] = temp; + } + start = i + 1; + } else { + end = i; + } + } + + //Process last word + mid = start + (end - start) / 2; + for (int j = start; j <= mid; j++) { + char temp = s[j]; + s[j] = s[end - (j - start)]; + s[end - (j - start)] = temp; + } + + } +} +``` \ No newline at end of file diff --git a/Java/Reverse Words in a String.java b/Java/Reverse Words in a String.java index 934ef0b..28178d2 100644 --- a/Java/Reverse Words in a String.java +++ b/Java/Reverse Words in a String.java @@ -1,25 +1,35 @@ -几种不同的方法flip: +M + +几种不同的方法flip: 坑: 1. 结尾不能有空格。 2. 注意,如果Input是 ‘ ’的话,split以后就啥也没有了。check split以后 length == 0 + +另个题目Reverse Words in String (char[]) 可以in-place,因为条件说char[]里面是没有首尾空格,好做许多哟. + ``` /* -23% Accepted Given an input string, reverse the string word by word. For example, Given s = "the sky is blue", return "blue is sky the". -Example -Clarification +Update (2015-02-12): +For C programmers: Try to solve it in-place in O(1) space. + +click to show clarification. + +Clarification: What constitutes a word? A sequence of non-space characters constitutes a word. - Could the input string contain leading or trailing spaces? Yes. However, your reversed string should not contain leading or trailing spaces. How about multiple spaces between two words? Reduce them to a single space in the reversed string. -Tags Expand -String +Hide Company Tags Bloomberg +Hide Tags String +Hide Similar Problems (M) Reverse Words in a String II + + */ @@ -27,7 +37,7 @@ /* - Thoughts:12.08.2015 + Thoughts:12.08.2015 Have multiple two other ways to do it: 1. flip all,then flip each individual word; 2. break into parts and append from end to beginning. @@ -57,7 +67,7 @@ public String reverseWords(String s) { /* -Thinking Process: +Thinking Process: 1. Reverse it like reversing a int array 2. Use Split into arrays. 3. When reversing, make sure not empty string "" diff --git a/Java/Roman to Integer.java b/Java/Roman to Integer.java new file mode 100755 index 0000000..0ca26cb --- /dev/null +++ b/Java/Roman to Integer.java @@ -0,0 +1,64 @@ +E + +熟悉罗马字母规则 +1. 'I V X L C D M' 分别代表的数字 +2. 'IV, IX'减1, 'XL, XC'减10, 'CD, CM'减100. + +``` +/* +Given a roman numeral, convert it to an integer. + +Input is guaranteed to be within the range from 1 to 3999. + +Hide Company Tags Bloomberg Uber +Hide Tags Math String +Hide Similar Problems (M) Integer to Roman + +*/ + + +//switch different char, add all together +//Letter representation, and 'less than' special combos + +public class Solution { + public int romanToInt(String s) { + if (s == null || s.length() == 0) { + return 0; + } + int num = 0; + for (int i = 0; i < s.length(); i++) { + switch(s.charAt(i)) { + case 'I': num += 1; break; + case 'V': num += 5; break; + case 'X': num += 10; break; + case 'L': num += 50; break; + case 'C': num += 100; break; + case 'D': num += 500; break; + case 'M': num += 1000; break; + default: + return 0; + } + } + + num -= countMatch(s, "IV") * 2; + num -= countMatch(s, "IX") * 2; + num -= countMatch(s, "XL") * 10 * 2; + num -= countMatch(s, "XC") * 10 * 2; + num -= countMatch(s, "CD") * 100 * 2; + num -= countMatch(s, "CM") * 100 * 2; + + return num; + } + + public int countMatch(String s, String key) { + int count = 0; + while (s.indexOf(key) != -1) { + count++; + int i = s.indexOf(key); + s = s.substring(i + 2); + } + return count; + } + +} +``` diff --git a/Java/Rotate Image.java b/Java/Rotate Image.java new file mode 100644 index 0000000..c832148 --- /dev/null +++ b/Java/Rotate Image.java @@ -0,0 +1,51 @@ +M + +找到个转角度的规律公式。用一个temp。in place. + +``` +/* +You are given an n x n 2D matrix representing an image. +Rotate the image by 90 degrees (clockwise). + +Have you met this question in a real interview? Yes +Example +Given a matrix + +[ + [1,2], + [3,4] +] +rotate it by 90 degrees (clockwise), return + +[ + [3,1], + [4,2] +] +Challenge +Do it in-place. + +Tags Expand +Cracking The Coding Interview Matrix +*/ + + +//in matrix, to find next position: r = c; c = (w - r). Work on the equation => oldR = w - c, oldC = r +//In pace: do loop, change 4 at once. do a quater of the matrix +public class Solution { + public void rotate(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return; + } + int width = matrix.length; + for (int i = 0; i < width/2; i++) { + for (int j = 0; j < Math.ceil(width/2.0); j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[width - 1 - j][i]; + matrix[width - 1 - j][i] = matrix[width - 1 - i][width - 1 - j]; + matrix[width - 1 - i][width - 1 - j] = matrix[j][width - 1 - i]; + matrix[j][width - 1 - i] = temp; + } + } + } +} +``` \ No newline at end of file diff --git a/Java/Search Range in Binary Search Tree .java b/Java/Search Range in Binary Search Tree .java old mode 100644 new mode 100755 index b7a9423..b74545d --- a/Java/Search Range in Binary Search Tree .java +++ b/Java/Search Range in Binary Search Tree .java @@ -1,6 +1,17 @@ +M + +等于遍历了所有k1<= x <= k2的x node。 + +如果是用Binary Search Tree搜索,那么一般是if (...) else {...},也就是一条路走到底,直到找到target. + +这里, 把 left/right/match的情况全部cover了,然后把k1,k2的边框限制好,中间就全部遍历了。 + +``` /* -37% Accepted -Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find all the keys of tree in range k1 to k2. i.e. print all x such that k1<=x<=k2 and x is a key of given BST. Return all the keys in ascending order. + +Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. +Find all the keys of tree in range k1 to k2. +i.e. print all x such that k1<=x<=k2 and x is a key of given BST. Return all the keys in ascending order. Example For example, if k1 = 10 and k2 = 22, then your function should print 12, 20 and 22. @@ -21,12 +32,12 @@ Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Thinking Process: Find lowest and turn around. - If don’t hit the ground, keep digging: - if (root.val > k1) dig into root.left + If don’t hit the ground, keep digging: + if (root.val > k1) dig into root.left Check current Find maximum and turn around. - If don’t hit the ceiling, keep climbing: - if (root.val < k2) climb to root.right + If don’t hit the ceiling, keep climbing: + if (root.val < k2) climb to root.right */ @@ -58,3 +69,5 @@ public void helper(ArrayList result, TreeNode root, int k1, int k2) { } } + +``` \ No newline at end of file diff --git a/Java/Search Rotated in Sorted Array II.java b/Java/Search Rotated in Sorted Array II.java old mode 100644 new mode 100755 diff --git a/Java/Search Rotated in Sorted Array.java b/Java/Search Rotated in Sorted Array.java old mode 100644 new mode 100755 index 7543d27..35538d1 --- a/Java/Search Rotated in Sorted Array.java +++ b/Java/Search Rotated in Sorted Array.java @@ -1,23 +1,27 @@ -方法1: - 1. binay search break point - 2. binary search target - 注意等号,在判断target在前半段还是后半段:if (A[p1] <= target && target <= A[breakPoint]) - -方法2: - 还是把它先当做正常的sorted list开始搜。 - 但是在比较的时候,多比较一个A[start] < A[mid]? - 在1 和 2 里面分别讨论 target 的位置 - 1. A[start] < A[mid] ? - 说明在前半段 - - start mid - 2. A[start] > A[mid] - 说明 start 还在前半段,而mid在后半段 - - mid < target < end - - target < mid +H + +方法1:O(logn) + 还是把它先当做正常的sorted list开始搜。 + 但是在比较的时候,多比较一个A[start] < A[mid]? + 在1 和 2 里面分别讨论 target 的位置 + 1. A[start] < A[mid] ? + 说明在前半段 + - start mid + 2. A[start] > A[mid] + 说明 start 还在前半段,而mid在后半段 + - mid < target < end + - target < mid +方法2:O(logn) + 1. binay search break point + 2. binary search target + 注意等号,在判断target在前半段还是后半段:if (A[p1] <= target && target <= A[breakPoint]) + + + ``` /* Suppose a sorted array is rotated at some pivot unknown to you beforehand. @@ -37,6 +41,57 @@ Binary Search Array Sorted Array */ + + +/* + Just 1 binary search: this is the better solution + //Observation: + //1. There is only one break point + //2. There has to be a side that's continous, either first section or second section. + //3. Need to locate that continous section, then check if target is part of the continous section + +*/ +public class Solution { + public int search(int[] A, int target) { + // write your code here + if (A.length == 0) { + return -1; + } + + int start = 0; + int end = A.length - 1; + int mid; + + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A[mid] == target) {//Check central point + return mid; + } + if (A[start] < A[mid]){//1st section is continous + if (A[start] <= target && target <= A[mid]) {//target in 1st section? + end = mid; + } else { + start = mid; + } + } else {//2nd section is continous + if (A[mid] <= target && target <= A[end]) {//target in 2nd section? + start = mid; + } else { + end = mid; + } + } + }//While + + if (A[start] == target) { + return start; + } else if (A[end] == target) { + return end; + } else { + return -1; + } + } +} + /* Easy solution: Find the break point, then decide which section to binary search @@ -101,60 +156,5 @@ public int search(int[] A, int target) { -/* - Just 1 binary search: this is the better solution - //Observation: - //1. There is only one break point - //2. There has to be a side that's continous, either first section or second section. - //3. Need to locate that continous section, then check if target is part of the continous section - -*/ -public class Solution { - /** - *@param A : an integer rotated sorted array - *@param target : an integer to be searched - *return : an integer - */ - - public int search(int[] A, int target) { - // write your code here - if (A.length == 0) { - return -1; - } - - int start = 0; - int end = A.length - 1; - int mid; - - while (start + 1 < end) { - mid = start + (end - start) / 2; - if (A[mid] == target) {//Check central point - return mid; - } - if (A[start] < A[mid]){//1st section is continous - if (A[start] <= target && target <= A[mid]) {//target in 1st section? - end = mid; - } else { - start = mid; - } - } else {//2nd section is continous - if (A[mid] <= target && target <= A[end]) {//target in 2nd section? - start = mid; - } else { - end = mid; - } - } - }//While - - if (A[start] == target) { - return start; - } else if (A[end] == target) { - return end; - } else { - return -1; - } - } -} - ``` \ No newline at end of file diff --git a/Java/Segment Tree Build II.java b/Java/Segment Tree Build II.java old mode 100644 new mode 100755 index 4c8b25f..b97f7df --- a/Java/Segment Tree Build II.java +++ b/Java/Segment Tree Build II.java @@ -1,10 +1,18 @@ -给的是Array。注意找区间内的max, assign给区间。 -想:区间break到底,像segment tree build I 里面一样最终也就是 start==end。也就是max=A[start] 或者A[end] -往上一层,其实max就是比较左右孩子。然后一次递推。每次找max其实都是在两个sub-tree里面比较sub-tree的max。 -这就好做了: +M + + +给的是Array。注意找区间内的max, assign给区间。 其余和普通的segment tree build一样 + +给了array,但是并不根据array里的内容排位,而是依然根据index in [0, array.length - 1]割开区间,break到底, +最终start==end。同时assign max=A[start] or A[end] + +往上,parent一层的max:就是比较左右孩子,其实都是在两个sub-tree里面比较sub-tree的max。 + +这就好做了: 先分,找到left/right,比较max,在create current node,再append到当前node上面。 实际上是depth-first, 自底向上建立起的。 + ``` /* The structure of Segment Tree is a binary tree which each node has two attributes start and end @@ -14,6 +22,7 @@ The left child of node A has start=A.left, end=(A.left + A.right) / 2. The right child of node A has start=(A.left + A.right) / 2 + 1, end=A.right. if start equals to end, there will be no children for this node. + Implement a build method with a given array, so that we can create a corresponding segment tree with every node value represent the corresponding interval max value in the array, return the root of this segment tree. diff --git a/Java/Segment Tree Build.java b/Java/Segment Tree Build.java old mode 100644 new mode 100755 index 32660c8..ae76e94 --- a/Java/Segment Tree Build.java +++ b/Java/Segment Tree Build.java @@ -1,9 +1,13 @@ -按定义: -左孩子:(A.left, (A.left+A.rigth)/2) -右孩子:((A.left+A.rigth)/2+1, A.right) +M + +按定义: +左孩子:(A.left, (A.left+A.rigth)/2) +右孩子:((A.left+A.rigth)/2+1, A.right) + ``` /* -The structure of Segment Tree is a binary tree which each node has two attributes start and end denote an segment / interval. +The structure of Segment Tree is a binary tree which each node +has two attributes start and end denote an segment / interval. start and end are both integers, they should be assigned in following rules: @@ -11,7 +15,8 @@ The left child of node A has start=A.left, end=(A.left + A.right) / 2. The right child of node A has start=(A.left + A.right) / 2 + 1, end=A.right. if start equals to end, there will be no children for this node. -Implement a build method with two parameters start and end, so that we can create a corresponding segment tree with every node has the correct start and end value, return the root of this segment tree. +Implement a build method with two parameters start and end, so that we can create a corresponding segment tree +with every node has the correct start and end value, return the root of this segment tree. Example Given start=0, end=3. The segment tree will be: @@ -62,4 +67,17 @@ public SegmentTreeNode build(int start, int end) { return node; } } + +/** + * Definition of SegmentTreeNode: + * public class SegmentTreeNode { + * public int start, end; + * public SegmentTreeNode left, right; + * public SegmentTreeNode(int start, int end) { + * this.start = start, this.end = end; + * this.left = this.right = null; + * } + * } + */ + ``` \ No newline at end of file diff --git a/Java/Segment Tree Modify.java b/Java/Segment Tree Modify.java old mode 100644 new mode 100755 index f506afe..f5a8b5c --- a/Java/Segment Tree Modify.java +++ b/Java/Segment Tree Modify.java @@ -1,12 +1,19 @@ -在segment tree里面找index. -找到就update it with value. -每次下一层以后,很可能(要么左手,要么右手)max就变了。所以每次都left.max and right.max compare一下。 -最后轮回到头顶,头顶一下包括头顶,就全部都是max了。 +M + +Recursively 在segment tree里面找index, update it with value. + +每个iteration,很可能(要么左手,要么右手)max就变了。所以每次都left.max and right.max compare一下。 +最后轮回到头顶,头顶一下包括头顶,就全部都是max了。 + +Divde and Conquer + ``` /* For a Maximum Segment Tree, which each node has an extra value max to store the maximum value in this node's interval. -Implement a modify function with three parameter root, index and value to change the node's value with [start, end] = [index, index] to the new given value. Make sure after this change, every node in segment tree still has the max attribute with the correct value. +Implement a modify function with three parameter root, +index and value to change the node's value with [start, end] = [index, index] to the new given value. +Make sure after this change, every node in segment tree still has the max attribute with the correct value. Example For segment tree: diff --git a/Java/Segment Tree Query II.java b/Java/Segment Tree Query II.java old mode 100644 new mode 100755 index 30b6ea6..8b376ce --- a/Java/Segment Tree Query II.java +++ b/Java/Segment Tree Query II.java @@ -1,11 +1,20 @@ +M + 和 Segment Tree Query I 以及其他Segment Tree问题没啥区别。这个就是return个count。 -这个题目考的是:validate input source... -搞不清楚LintCode出这个题目干啥。 + +这个题目考了validate input source:input 的start,end可能超出root[start,end]。 +那么第一步就要先clear一下。完全不在range就return 0. 有range重合就规整到root的range. + + + ``` /* -For an array, we can build a SegmentTree for it, each node stores an extra attribute count to denote the number of elements in the the array which value is between interval start and end. (The array may not fully filled by elements) +For an array, we can build a SegmentTree for it, each node stores an extra attribute count to +denote the number of elements in the the array which value is between interval start and end. +(The array may not fully filled by elements) -Design a query method with three parameters root, start and end, find the number of elements in the in array's interval [start, end] by the given root of value SegmentTree. +Design a query method with three parameters root, start and end, +find the number of elements in the in array's interval [start, end] by the given root of value SegmentTree. Example For array [0, 2, 3], the corresponding value Segment Tree is: @@ -64,16 +73,19 @@ public int query(SegmentTreeNode root, int start, int end) { if (root.start == start && root.end == end) { return root.count; } - //Check if over range - if ((start < root.start && end > root.end) || - (start < root.start && end < root.start) || + + //Check if out range. If so, set border to root[start,end] + if ((start < root.start && end < root.start) || (start > root.end && end > root.end)) { return 0; - } else if (start < root.start && end <= root.end) { + } + if (start < root.start) { start = root.start; - } else if (start >= root.start && end > root.end) { + } + if (end > root.end) { end = root.end; } + int mid = (root.start + root.end)/2; if (end <= mid) { return query(root.left, start, end); @@ -81,6 +93,7 @@ public int query(SegmentTreeNode root, int start, int end) { if (start > mid) { return query(root.right, start, end); } + //mid in between [start, end] return query(root.left, start, root.left.end) + query(root.right, root.right.start, end); } } diff --git a/Java/Segment Tree Query.java b/Java/Segment Tree Query.java old mode 100644 new mode 100755 index 05f9749..f2788c5 --- a/Java/Segment Tree Query.java +++ b/Java/Segment Tree Query.java @@ -1,15 +1,23 @@ -[start,end]跟mid相比,可能: -全在mid左 -全在mid右 -包含了mid: 这里要特别break into 2 query method +M -按定义: +给了segment Tree, node里面有Max value, 找[start,end]里面的max + +[start,end]跟mid相比,可能: +全在mid左 +全在mid右 +包含了mid: 这里要特别break into 2 query method + +按定义: mid = (root.start + root.end)/2 + ``` /* -For an integer array (index from 0 to n-1, where n is the size of this array), in the corresponding SegmentTree, each node stores an extra attribute max to denote the maximum number in the interval of the array (index from start to end). +For an integer array (index from 0 to n-1, where n is the size of this array), +in the corresponding SegmentTree, each node stores an extra attribute max to denote +the maximum number in the interval of the array (index from start to end). -Design a query method with three parameters root, start and end, find the maximum number in the interval [start, end] by the given root of segment tree. +Design a query method with three parameters root, start and end, + find the maximum number in the interval [start, end] by the given root of segment tree. Example For array [1, 4, 2, 3], the corresponding Segment Tree is: diff --git a/Java/Sliding Window Maximum.java b/Java/Sliding Window Maximum.java old mode 100644 new mode 100755 diff --git a/Java/Sliding Window Median.java b/Java/Sliding Window Median.java old mode 100644 new mode 100755 diff --git a/Java/String to Integer(atoi).java b/Java/String to Integer(atoi).java index 649e926..9c7f895 100644 --- a/Java/String to Integer(atoi).java +++ b/Java/String to Integer(atoi).java @@ -1,3 +1,10 @@ +E + +方法1: 问清情况,一点一点把case都涉及到。 + +方法2: 用regular expression。if (!str.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)")). 猛了一点 + +``` /* Implement function atoi to convert a string to an integer. @@ -17,6 +24,61 @@ If the correct value is out of the range of representable values, INT_MAX (21474 Tags Expand Basic Implementation String +*/ + + +/* +02.02.2016 from leetcode +Requirements for atoi: +The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. + +The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function. + +If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed. + +If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. +*/ +public class Solution { + public int myAtoi(String str) { + + if (str == null) { + return 0; + } + str = str.trim(); + if (str.length() == 0) { + return 0; + } + + char[] arr = str.toCharArray(); + String rst = ""; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (i == 0 && (c == '+' || c == '-')) { + rst += c; + } else if (c < '0' || c > '9') { + break; + } else { + rst += c; + } + } + if (rst.length() == 0 || rst.equals("+") || rst.equals("-")) { + return 0; + } + if (rst.length() > 11) { + return rst.charAt(0) == '-' ? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + long largeNum = Long.parseLong(rst); + if (largeNum > Integer.MAX_VALUE || largeNum < Integer.MIN_VALUE) { + return largeNum > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + return Integer.parseInt(rst); + } +} + + + +/* + Thoughts: First idea: why not using Integer.parseInt(str)? Maybe that's too costly, and maybe it does not over all possible integers? Can we just use a Long.parseLong(str) ? @@ -32,7 +94,6 @@ If the correct value is out of the range of representable values, INT_MAX (21474 */ - public class Solution { /** * @param str: A string @@ -40,19 +101,22 @@ public class Solution { */ public int atoi(String str) { if (str == null || str.length() == 0) { - return 0; + return 0; } str = str.replaceAll("\\s",""); if (!str.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)")) { - return 0; + return 0; } double rst = Double.parseDouble(str); if (rst > Integer.MAX_VALUE) { - return Integer.MAX_VALUE; + return Integer.MAX_VALUE; } else if (rst < Integer.MIN_VALUE) { - return Integer.MIN_VALUE; + return Integer.MIN_VALUE; } else { - return (int)rst; + return (int)rst; } } -} \ No newline at end of file +} + + +``` \ No newline at end of file diff --git a/Java/Strobogrammatic Number II.java b/Java/Strobogrammatic Number II.java new file mode 100644 index 0000000..9d47fa6 --- /dev/null +++ b/Java/Strobogrammatic Number II.java @@ -0,0 +1,73 @@ +耗了一点时间。本以为需要DP一下,把做过的n存一下。后来发现,其实就是剥皮,一层一层,是一个central-depth-first的,钻到底时候,return n=1,或者n=2的case,然后开始backtracking。 +难的case先不handle.到底之后来一次O(n) scan. +总共的时间起码是O(n/2) + O(n), 所以还是O(n) +``` +/* +A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). + +Find all strobogrammatic numbers that are of length = n. + +For example, +Given n = 2, return ["11","69","88","96"]. + +Hint: +Try to use recursion and notice that it should recurse with n - 2 instead of n - 1. + +Tags: Math Recursion +Similar Problems: (E) Strobogrammatic Number, (H) Strobogrammatic Number III + +*/ +/* +Thoughts: +For n, there can be k kinds of combination. Save it to map(n,k-list) +For n+2, there can be x + k-kinds-of-inner-number + y; +Treat n=0,1,2 differently. Then recurse on rest, layer by layer +At end end, do a O(n) scan to remove non-wanted items. +*/ +public class Solution { + private HashMap candidate = new HashMap(); + public List findStrobogrammatic(int n) { + List rst = new ArrayList(); + candidate.put("0", "0"); + candidate.put("1", "1"); + candidate.put("8", "8"); + candidate.put("6", "9"); + candidate.put("9", "6"); + rst = searchAndCombine(n); + for (int i = 0; i < rst.size(); i++) { + if ((Long.parseLong(rst.get(i))+"").length() != n) { + rst.remove(i); + i--; + } + } + return rst; + } + + public List searchAndCombine(int n) { + List list = new ArrayList(); + if (n <= 0) { + return list; + } else if (n == 1) { + list.add("0"); + list.add("1"); + list.add("8"); + return list; + } else if (n == 2){ + list.add("69"); + list.add("11"); + list.add("88"); + list.add("96"); + list.add("00"); + return list; + }else {//n >= 2 + List temp = searchAndCombine(n - 2); + for (String str : temp) { + for (Map.Entry entry : candidate.entrySet()) { + list.add(entry.getKey() + str + entry.getValue()); + } + } + } + return list; + } +} +``` \ No newline at end of file diff --git a/Java/Strobogrammatic Number.java b/Java/Strobogrammatic Number.java new file mode 100644 index 0000000..9d7d0eb --- /dev/null +++ b/Java/Strobogrammatic Number.java @@ -0,0 +1,83 @@ +/* +A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). +Write a function to determine if a number is strobogrammatic. The number is represented as a string. +For example, the numbers "69", "88", and "818" are all strobogrammatic. +Tags: Hash Table Math +Similar Problems: (M) Strobogrammatic Number II, (H) Strobogrammatic Number III +*/ + +/* +OPTS 11.04.2015 +Thoughts: +Because the symmetric pairs are: +1-1, 8-8,0-0,6-9,9-6, we make a hashmap of it. +Create left/right pointer, where each compare has to match the pair in hashmap. + +Note: +On map.containsKey() line, need to check (right), or whichever item that map is going to map.get(...) afterwards. +If containsKey fails, return false; only when it passes through, then proceed to mpa.get() +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + HashMap map = new HashMap(); + map.put('0','0'); + map.put('1','1'); + map.put('8','8'); + map.put('6','9'); + map.put('9','6'); + int left = 0; + int right = num.length() - 1; + while (left <= right) { + if (!map.containsKey(num.charAt(right)) || num.charAt(left) != map.get(num.charAt(right))) { + return false; + } + left++; + right--; + } + return true; + } +} + +/* +Thoughts: +Compare digits to the symmetric postion; special care for (6,9) pair, mark it after comparision. +Elimite the cases before the for-loop run through(can do it in or as well, but that just make the code a bit complex) +Note: +Didn't use HashMap. I beleive hash map is used to mark the spot? +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + //Any non-strobogrammatic + if (num.indexOf("2") >= 0 || num.indexOf("3") >= 0 || + num.indexOf("4") >= 0 || num.indexOf("5") >= 0 || + num.indexOf("7") >= 0) { + return false; + } + //If only 6 or 9 exist: + if ((num.indexOf("6") >= 0 && num.indexOf("9") < 0) || + (num.indexOf("9") >= 0 && num.indexOf("6") < 0)) { + return false; + } + //Check if (6,9) or other strobogrammatic # are appearing at symmetric position + char[] arr = num.toCharArray(); + int leng = num.length(); + for (int i = 0; i < leng; i++) { + if (arr[i] == '6' || arr[i] == '9') { + if ((arr[i] == '6' && arr[leng - i - 1] != '9') || + (arr[i] == '9' && arr[leng - i - 1] != '6')) { + return false; + } + arr[i] = arr[leng - i - 1] = 'M';//marker + } else if (arr[i] != 'M' && arr[i] != arr[leng - i - 1]) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Java/Subarray Sum Closest.java b/Java/Subarray Sum Closest.java old mode 100644 new mode 100755 index 8422953..1435971 --- a/Java/Subarray Sum Closest.java +++ b/Java/Subarray Sum Closest.java @@ -1,3 +1,8 @@ +M + +? + +``` /* Given an integer array, find a subarray with sum closest to zero. Return the indexes of the first number and last number. @@ -145,3 +150,5 @@ public static void main(String[] args){ + +``` \ No newline at end of file diff --git a/Java/Subarray Sum.java b/Java/Subarray Sum.java old mode 100644 new mode 100755 index ab42c31..709018f --- a/Java/Subarray Sum.java +++ b/Java/Subarray Sum.java @@ -1,5 +1,13 @@ +E + +分析出,如果sum[0~a]=x, 然后sum[0~b]=x, 说明sum(a ~ b] = 0. + + 这样理解后,用hashMap存每个sum[0~i]的值和index i. 如果有重复,就找到了一组sum为0的数组。 + +``` /* -Given an integer array, find a subarray where the sum of numbers is zero. Your code should return the index of the first number and the index of the last number. +Given an integer array, find a subarray where the sum of numbers is zero. +Your code should return the index of the first number and the index of the last number. Example Given [-3, 1, 2, -3, 4], return [0, 2] or [1, 3]. @@ -9,7 +17,9 @@ Tags Expand Subarray Hash Table +*/ +/* Thougths: Record the sum from (0 ~ a). Check sum on each index i, when found an existing sum in the hashMap, we are done. @@ -19,11 +29,7 @@ Record the sum from (0 ~ a). As result, hashmap.get(a)+1 will be the satrting index, and b will be ending index. */ public class Solution { - /** - * @param nums: A list of integers - * @return: A list of integers includes the index of the first number - * and the index of the last number - */ + public ArrayList subarraySum(int[] nums) { ArrayList rst = new ArrayList(); if (nums == null || nums.length == 0) { @@ -45,3 +51,5 @@ public ArrayList subarraySum(int[] nums) { return rst; } } + +``` \ No newline at end of file diff --git a/Java/Subset.java b/Java/Subset.java old mode 100644 new mode 100755 index 5d47859..ee60e50 --- a/Java/Subset.java +++ b/Java/Subset.java @@ -1,8 +1,17 @@ -最基本的递归题目。 -坑:记得一开头sort一下 nums。 因为要升序。 +M + +最基本的递归题目。 +坑:记得一开头sort一下 nums。 因为要升序。那么整体就是O(nlogn) + +注意:用level/index来track到哪一步。最后一level就add into rst + +方法1: subset的概念,取或者不取,backtracking. 当level/index到底,return 一个list. + +方法2: 用for loop backtracking. 记得:每个dfs recursive call是一种独特可能,先加进rst。 + + +recap:时间久了忘记dfs的两种路子. for loop dfs/backtracking vs. regular dfs -点: -用level来track到哪一步。最后一level就add into rst ``` /* Given a set of distinct integers, return all possible subsets. @@ -31,15 +40,13 @@ */ /* - 12.06.2015 recap: + 12.06.2015 recap. + Choose or not choose + When level == nums.length, return a entry. */ class Solution { - /** - * @param S: A set of numbers. - * @return: A list of lists. All valid subsets. - */ - public ArrayList> subsets(int[] nums) { - ArrayList> rst = new ArrayList>(); + public List> subsets(int[] nums) { + List> rst = new ArrayList>(); if (nums == null || nums.length == 0) { return rst; } @@ -49,7 +56,7 @@ public ArrayList> subsets(int[] nums) { return rst; } - public void helper(ArrayList> rst, ArrayList list, + public void helper(List> rst, ArrayList list, int[] nums, int level) { if (level == nums.length) { rst.add(new ArrayList(list)); @@ -66,27 +73,28 @@ public void helper(ArrayList> rst, ArrayList list, } - - public ArrayList> subsets(ArrayList source) { - // write your code here - ArrayList> output = new ArrayList>(); - ArrayList newList = new ArrayList(); - Collections.sort(source); - subsetHelper(0, source, newList, output); - return output; +//Back tracking, DFS, recursive: recursive call of (rst, list, nums, index). +class Solution { + public List> subsets(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + Arrays.sort(nums); + ArrayList list = new ArrayList(); + dfs(rst, list, nums, 0); + return rst; } - public void subsetHelper(int pos, - ArrayList source, ArrayList newList, - ArrayList> output){ - output.add(new ArrayList(newList)); + public void dfs(List> rst, ArrayList list, int[] nums, int index){ + rst.add(new ArrayList<>(list)); - for( int i = pos; i < source.size(); i++){ - newList.add( source.get(i)); - subsetHelper(i+1, source, newList, output); - newList.remove( newList.size() - 1 ); + for( int i = index; i < nums.length; i++){ + list.add(nums[i]); + dfs(rst, list, nums, i+1); + list.remove(list.size() - 1); } } - +} ``` \ No newline at end of file diff --git a/Java/Subsets II.java b/Java/Subsets II.java old mode 100644 new mode 100755 index b73756c..7a9f38b --- a/Java/Subsets II.java +++ b/Java/Subsets II.java @@ -1,6 +1,23 @@ -递归:找准需要pass along的几个数据结构。 +M + +递归:找准需要pass along的几个数据结构。 + +和SubsetI类似,先sort input, 然后递归。但是input可能有duplicates. + +Using for loop approach: 每个dfs call是一种可能性,直接add into result. +为了除去duplicated result, 如果在递归里面用rst.contains(),就是O(n), which makes overall O(n^2). + +这里有个基于sorted array的技巧: +因为我们有mark index。 一旦for loop里面的i!=index,并且nums[i] == nums[i-1],说明x=nums[i-1]已经用过,不需要再用一次: +[a,x1,x2],x1==x2 +i == index -> [a,x1] +i == index + 1 -> [a,x2]. 我们要skip这一种。 + +如果需要[a,x1,x2]怎么办? 其实这一种在index变化时,会在不同的两个dfs call 里面涉及到。 + + +Iterative: 写一写,用个Queue. Not recommended, Again, rst.contains() cost too much. -Iterative: 写一写,用个Queue. ``` /* Given a list of numbers that may has duplicate numbers, return all possible subsets @@ -29,6 +46,46 @@ */ /* +03.10.2016 +Once sorted at beginning, same num are ajacent. +With for loop solution, we are jumping to next position in one dfs call, so this could happen: +skip current and take next. if current == next, that generates duplicates. +Image we've moved one step forward already, so we are not on given index, also current == prev: +that means previous position nums[i-1] must have been used. so we skip the current. +if (i != index && nums[i] == nums[i - 1]) { + continue; +} +*/ +public class Solution { + public List> subsetsWithDup(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + + Arrays.sort(nums); + dfs(rst, new ArrayList(), 0, nums); + + return rst; + } + + public void dfs(List> rst, ArrayList list, int index, int[] nums) { + rst.add(new ArrayList(list)); + + for (int i = index; i < nums.length; i++) { + if (i != index && nums[i] == nums[i - 1]) { + continue; + } + list.add(nums[i]); + dfs(rst, list, i + 1, nums); + list.remove(list.size() - 1); + + } + } +} + +/* + Not recommended, Again, rst.contains() cost too much. Thoughts: 12.07.2015 try to do non-recursive - iterative @@ -40,10 +97,6 @@ */ class Solution { - /** - * @param S: A set of numbers. - * @return: A list of lists. All valid subsets. - */ public ArrayList> subsetsWithDup(ArrayList S) { ArrayList> rst = new ArrayList>(); if (S == null || S.size() == 0) { @@ -62,7 +115,7 @@ public ArrayList> subsetsWithDup(ArrayList S) { list = queue.poll(); //Pick list.add(num); - if (!rst.contains(list)) { + if (!rst.contains(list)) {//O(n) rst.add(new ArrayList(list)); } queue.offer(new ArrayList(list)); @@ -80,16 +133,13 @@ public ArrayList> subsetsWithDup(ArrayList S) { /* + Not recommended, Again, rst.contains() cost too much. Thoughts: 12.07.2015. Do regular subset recursion: pick curr or not pick curr, (rst, list, level, S) Use a HashMap to mark if the cmobination exists already Recursive. */ class Solution { - /** - * @param S: A set of numbers. - * @return: A list of lists. All valid subsets. - */ public ArrayList> subsetsWithDup(ArrayList S) { ArrayList> rst = new ArrayList>(); if (S == null || S.size() == 0) { @@ -104,7 +154,7 @@ public ArrayList> subsetsWithDup(ArrayList S) { public void helper(ArrayList> rst, ArrayList list, ArrayList S, int level) { - if (!rst.contains(list)) { + if (!rst.contains(list)) {//Costly, O(n) each time rst.add(new ArrayList(list)); } if (level == S.size()) { @@ -125,37 +175,31 @@ public void helper(ArrayList> rst, ArrayList list, -//Older version, with for loop: - - -class Solution { - /** - * @param S: A set of numbers. - * @return: A list of lists. All valid subsets. - */ - public ArrayList> subsetsWithDup(ArrayList source) { - // write your code here - ArrayList> output = new ArrayList>(); - ArrayList newList = new ArrayList(); - Collections.sort(source); - subsetHelper(0, source, newList, output); - return output; +//Older version, with for loop, use rst.contains()... which is very costly, O(n) each time +// Not recommended, Again, rst.contains() cost too much. +public class Solution { + public List> subsetsWithDup(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + + Arrays.sort(nums); + dfs(rst, new ArrayList(), 0, nums); + + return rst; } - - public void subsetHelper(int pos, - ArrayList source, ArrayList newList, - ArrayList> output){ - if (!output.contains(newList)){ - output.add(new ArrayList(newList)); + public void dfs(List> rst, ArrayList list, int index, int[] nums) { + if (!rst.contains(list)) {//Costly, O(n) + rst.add(new ArrayList(list)); } - for (int i = pos; i < source.size(); i++){ - newList.add(source.get(i)); - subsetHelper(i + 1, source, newList, output); - newList.remove(newList.size() - 1); + for (int i = index; i < nums.length; i++) { + list.add(nums[i]); + dfs(rst, list, i + 1, nums); + list.remove(list.size() - 1); } - } } ``` \ No newline at end of file diff --git a/Java/Subtree.java b/Java/Subtree.java index f049e3b..0decfa9 100644 --- a/Java/Subtree.java +++ b/Java/Subtree.java @@ -1,3 +1,10 @@ +E + +找到potential subtree, 比较Children. + +一点注意:即使找到T1 == T2, 但很可能只是数字相同(这里不是binary search tree!!),而children不同。所以同时要继续recursively isSubtree(T1.left, T2) ...etc. + +``` /* You have two every large binary trees: T1, with millions of nodes, and T2, with hundreds of nodes. Create an algorithm to decide if T2 is a subtree of T1. @@ -47,25 +54,60 @@ public class Solution { * @return: True if T2 is a subtree of T1, or false. */ public boolean isSubtree(TreeNode T1, TreeNode T2) { - if (T2 == null) { - return true; - } else if (T1 == null) { - return false; - } else { - return compare(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2); - } + if (T2 == null) { + return true; + } else if (T1 == null) { + return false; + } else { + return compare(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2); + } } - //Recursive compare + //Recursive compare public boolean compare(TreeNode node1, TreeNode node2) { - if (node1 == null && node2 == null) { - return true; - } - if (node1 == null || node2 == null){ - return false; - } - if (node1.val != node2.val) { - return false; - } - return compare(node1.left, node2.left) && compare(node1.right, node2.right); + if (node1 == null && node2 == null) { + return true; + } + if (node1 == null || node2 == null){ + return false; + } + if (node1.val != node2.val) { + return false; + } + return compare(node1.left, node2.left) && compare(node1.right, node2.right); } } + + +// 2.22 recap: Find T2 first, then do a divide and conquer compare +public class Solution { + /** + * @param T1, T2: The roots of binary tree. + * @return: True if T2 is a subtree of T1, or false. + */ + public boolean isSubtree(TreeNode T1, TreeNode T2) { + if (T1 == null || T2 == null) { + return T2 == null; + } + + if (T1.val == T2.val) { + return compare(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2); + } else { + return isSubtree(T1.left, T2) || isSubtree(T1.right, T2); + } + } + + public boolean compare(TreeNode T1, TreeNode T2) { + if (T1 == null && T2 == null) { + return true; + } else if (T1 == null || T2 == null) { + return false; + } + if (T1.val != T2.val) { + return false; + } + + return compare(T1.left, T2.left) && compare(T1.right, T2.right); + } +} + +``` \ No newline at end of file diff --git a/Java/Summary Ranges.java b/Java/Summary Ranges.java new file mode 100644 index 0000000..f6370f5 --- /dev/null +++ b/Java/Summary Ranges.java @@ -0,0 +1,37 @@ +/* +Given a sorted integer array without duplicates, return the summary of its ranges. + +For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. + +Tags: Array +Similar Problems: (M) Missing Ranges + + +*/ +/* +Thoughts: basic implementation, use a arraylist to catch candidates. +Detect condition, and return results. +*/ +public class Solution { + public List summaryRanges(int[] nums) { + List rst = new ArrayList(); + if (nums == null || nums.length == 0) { + return rst; + } + ArrayList list = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + list.add(nums[i]); + if (i + 1 == nums.length || nums[i] + 1 != nums[i + 1]) { + if (list.size() == 1) { + rst.add(list.get(0) + ""); + } else { + rst.add(list.get(0) + "->" + list.get(list.size() - 1)); + } + list = new ArrayList(); + } + } + return rst; + } +} + +//O(n) \ No newline at end of file diff --git a/Java/Surrounded Regions.java b/Java/Surrounded Regions.java new file mode 100644 index 0000000..3cb5138 --- /dev/null +++ b/Java/Surrounded Regions.java @@ -0,0 +1,152 @@ +/* +Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. + +A region is captured by flipping all 'O's into 'X's in that surrounded region. + +For example, +X X X X +X O O X +X X O X +X O X X +After running your function, the board should be: + +X X X X +X X X X +X X X X +X O X X +Hide Tags Breadth-first Search + +Thinking Process: +Since dfs does not work, try bfs. +Very similar to DFS, however, when checking the 4 bounaries: +1. chcek the curruent point. +2. Add surrounding points into a queue. +3. Deal with the queue immediately via a while loop + +*/ +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + private Queue queue = new LinkedList(); + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + row = board.length; + col = board[0].length; + target = 'O'; + mark = 'M'; + //Check the board + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || i == row - 1 || j == 0 || j == col - 1) { + check(i,j); + } + } + } + //Replacement + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } + if (board[i][j] == mark) { + board[i][j] = target; + } + } + } + } + //BFS + public void check(int i, int j) { + fill(board, i, j); + while(!queue.isEmpty()) { + int val = queue.poll(); + int x = val / col; + int y = val % col; + fill(board, x - 1, y); + fill(board, x + 1, y); + fill(board, x, y - 1); + fill(board, x, y + 1); + } + } + public void fill(char[][] board, int i, int j) { + if (i < 0 || i >= row || j < 0 || j >= col || board[i][j] != target) { + return; + } + board[i][j] = mark; + queue.offer(i * col + j); + } +} + + + + +/* +Thinking process: +Using DFS. +1. Whenever the edge has an 'O', all touching point with 'O' will be non-surrounded by 'X'. SO check the 4 bounds first. Mark all non-surrounded point as M. +2. Replace all remaining 'O' with 'X' +3. Replace 'M' with 'O' +However, in the LeetCode test, DFS gives stack overflow. So we'd use BFS instead. +*/ + +/* + +//The following is using DFS, but gives Stackoverflow. +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + target = 'O'; + mark = 'M'; + row = board.length; + col = board[0].length; + + //check bound + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || j == 0 || i == row - 1 || j == col - 1) { + check(i, j); + } + } + } + //1. replace remaining target with 'x' + //2. replace all mark with 'O' + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } else if (board[i][j] == mark) { + board[i][j] = 'O'; + } + } + } + } + + public void check(int i, int j) { + if (i < 0 || j < 0 || i > row - 1 || j > col - 1) { + return; + } + if (board[i][j] == target) { + board[i][j] = mark; + check(i - 1, j); + check(i + 1, j); + check(i, j - 1); + check(i, j + 1); + } + } + +} + +*/ diff --git a/Java/Symmetric Binary Tree.java b/Java/Symmetric Binary Tree.java index dd7d52c..70d0885 100644 --- a/Java/Symmetric Binary Tree.java +++ b/Java/Symmetric Binary Tree.java @@ -1,5 +1,12 @@ -注意Symmetric Binary Tree的例子和定义。 -并不是说左右两个tree相等。 +E + +注意Symmetric Binary Tree的例子和定义: 是镜面一样的对称. 并不是说左右两个sub-tree相等。 + +方法1: Recursively check symmetrically相对应的Node. 每个node的children都和镜面另外一边相对的node的children刚好成镜面反射位置。 + +方法2: 用stack. 左手边sub-tree先加left,再加right child; 右手边sub-tree先加right child, 再加left child。 +process时,若symmetric,所有stack里面出来的node会一一对应。 + ``` /* Given a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center). @@ -112,4 +119,4 @@ public boolean isSymmetric(TreeNode root) { -``` \ No newline at end of file +``` diff --git a/Java/Top K Frequent Words.java b/Java/Top K Frequent Words.java new file mode 100755 index 0000000..e96c873 --- /dev/null +++ b/Java/Top K Frequent Words.java @@ -0,0 +1,140 @@ +M + +方法1:Brutle force用HashMap存frequency, 用ArrayList存lists of words。最后返回从尾部向前数的k个。 + 注意排序时Collection.sort()的cost是O(nLogk) + +方法1-1: 还是用HashMap,但create一个Node class, 然后用PriorityQueue. +PriorityQueue里面用到了 String.compareTo(another String).巧妙。 + +方法2: Trie && MinHeap屌炸天 + http://www.geeksforgeeks.org/find-the-k-most-frequent-words-from-a-file/ + +``` +/* +Given a list of words and an integer k, return the top k frequent words in the list. + +Example +Given + +[ + "yes", "lint", "code", + "yes", "code", "baby", + "you", "baby", "chrome", + "safari", "lint", "code", + "body", "lint", "code" +] +for k = 3, return ["code", "lint", "baby"]. + +for k = 4, return ["code", "lint", "baby", "yes"], + +Note +You should order the words by the frequency of them in the return list, the most frequent one comes first. If two words has the same frequency, the one with lower alphabetical order come first. + +Challenge +Do it in O(nlogk) time and O(n) extra space. + +Extra points if you can do it in O(n) time with O(k) extra space. + +Tags Expand +Hash Table Heap Priority Queue +*/ + +//2.23.2016 recap: +//Use priorityQueue and a Class node. PriorityQueue uses String.compareTo() +public class Solution { + class Node { + int freq; + String str; + public Node(String str, int freq){ + this.str = str; + this.freq = freq; + } + } + public String[] topKFrequentWords(String[] words, int k) { + String[] rst = new String[k]; + if (words == null || words.length == 0 || k <= 0) { + return rst; + } + //map + HashMap map = new HashMap(); + for (int i = 0 ; i < words.length; i++) { + if (!map.containsKey(words[i])) { + map.put(words[i], new Node(words[i], 0)); + } + map.get(words[i]).freq = map.get(words[i]).freq + 1; + } + //queue + PriorityQueue queue = new PriorityQueue(k, new Comparator(){ + public int compare(Node a, Node b) { + if (a.freq == b.freq) { + return a.str.compareTo(b.str); + } else { + return b.freq - a.freq; + } + } + }); + for (Map.Entry entry : map.entrySet()) { + queue.offer(entry.getValue()); + } + //output + for (int i = 0; i < k; i++) { + rst[i] = queue.poll().str; + } + + return rst; + } +} + + +/* + Attempt1, Thoughts: + Brutle force + HashMap, size n. O(n) + ArrayList> lists: each entry has a list of strings with index as frequency. O(n) + Adding to result String[], do a Collections.sort(), which cause O(nlogk) with a O(n) for loop on top; It becomes O(nLogk)on average. + Return lists' top k. +*/ +public class Solution { + public String[] topKFrequentWords(String[] words, int k) { + String[] rst = new String[k]; + if (words == null || words.length == 0 || k <= 0) { + return rst; + } + + HashMap map = new HashMap(); + ArrayList> lists = new ArrayList>(); + for (int i = 0; i <= words.length; i++) { + lists.add(new ArrayList()); + } + //Fill map + for (int i = 0; i < words.length; i++) { + if (!map.containsKey(words[i])) { + map.put(words[i], 0); + } + map.put(words[i], map.get(words[i]) + 1); + } + //Fill ArrayList + for (Map.Entry entry : map.entrySet()) { + int freqIndex = entry.getValue(); + lists.get(freqIndex).add(entry.getKey()); + } + + int count = 0; + for (int i = lists.size() - 1; i >= 0; i--) { + ArrayList list = lists.get(i); + Collections.sort(list); + for (int j = 0; j < list.size(); j++) { + if (count < k) { + rst[count] = list.get(j); + count++; + } + if (count >= k) { + return rst; + } + } + } + + return rst; + } +} +``` \ No newline at end of file diff --git a/Java/Topological Sorting.java b/Java/Topological Sorting.java index 3b4aa87..9dc400e 100644 --- a/Java/Topological Sorting.java +++ b/Java/Topological Sorting.java @@ -1,3 +1,21 @@ +M + +比较特别的BFS. + +几个graph的condition: +1. 可能有多个root +2. directed node, 可以direct backwards. + +Steps: +Track all neighbors/childrens. 把所有的children都存在map里面 +先把所有的root加一遍,可能多个root。并且全部加到queue里面。 + +然后以process queue, do BFS: +Only when map.get(label) == 0, add into queue && rst. +这用map track apperance, 确保在后面出现的node, 一定最后process. + + +``` /* Given an directed graph, a topological order of the graph nodes is defined as follow: @@ -51,40 +69,42 @@ public class Solution { public ArrayList topSort(ArrayList graph) { ArrayList rst = new ArrayList(); if (graph == null || graph.size() == 0) { - return graph; + return graph; } - //Keep track of all neighbors in HashMap + //Keep track of all neighbors in HashMap HashMap map = new HashMap(); for (DirectedGraphNode node : graph) { - for (DirectedGraphNode neighbor : node.neighbors) { - int keyN = neighbor.label; - if (map.containsKey(keyN)) { - map.put(keyN, map.get(keyN) + 1); - } else { - map.put(keyN, 1); - } - } + for (DirectedGraphNode neighbor : node.neighbors) { + int keyN = neighbor.label; + if (map.containsKey(keyN)) { + map.put(keyN, map.get(keyN) + 1); + } else { + map.put(keyN, 1); + } + } } //BFS: Add root node. Note: Queue queue = new LinkedList(); for (DirectedGraphNode node : graph) { - if (!map.containsKey(node.label)) { - queue.offer(node); - rst.add(node); - } + if (!map.containsKey(node.label)) { + queue.offer(node); + rst.add(node); + } } //BFS: go through all children while (!queue.isEmpty()) { - DirectedGraphNode node = queue.poll(); - for (DirectedGraphNode n : node.neighbors) { - int label = n.label; - map.put(label, map.get(label) - 1); - if (map.get(label) == 0) { - rst.add(n); - queue.offer(n); - } - } + DirectedGraphNode node = queue.poll(); + for (DirectedGraphNode n : node.neighbors) { + int label = n.label; + map.put(label, map.get(label) - 1); + if (map.get(label) == 0) { + rst.add(n); + queue.offer(n); + } + } } return rst; } } + +``` \ No newline at end of file diff --git a/Java/Trapping Rain Water II.java b/Java/Trapping Rain Water II.java old mode 100644 new mode 100755 index bf459ec..e02fca9 --- a/Java/Trapping Rain Water II.java +++ b/Java/Trapping Rain Water II.java @@ -1,6 +1,25 @@ +H + +用PriorityQueue把选中的height排序。为走位,create class Cell {x,y, height}. + +注意几个理论: +1. 从matrix四周开始考虑,发现matrix能Hold住的水,取决于height低的block。 +2. 必须从外围开始考虑,因为水是被包裹在里面,外面至少需要现有一层。 + +以上两点就促使我们用min-heap: 也就是natural order的PriorityQueue. + +process的时候,画个图也可以搞清楚,就是四个方向都走走,用curr cell的高度减去周围cell的高度。 若大于零,那么就有积水。 + +每个visited的cell都要mark. 去到4个方向的cell,加进queue里面继续process. + +这里,有一点,和trapping water I 想法一样。刚刚从外围,只是能加到跟外围cell高度一致的水平面。往里面,很可能cell高度变化。 +这里要附上curr cell 和 move-to cell的最大高度。 + +``` /* Trapping Rain Water II -Given n x m non-negative integers representing an elevation map 2d where the area of each cell is 1 x 1, compute how much water it is able to trap after raining. +Given n x m non-negative integers representing an elevation map 2d +where the area of each cell is 1 x 1, compute how much water it is able to trap after raining. Example @@ -41,79 +60,68 @@ */ public class Solution { - class Cell { - int x; - int y; - int h; - public Cell(int x, int y, int height) { - this.x = x; - this.y = y; - this.h = height; - } - } + class Cell { + int x; + int y; + int h; + public Cell(int x, int y, int height) { + this.x = x; + this.y = y; + this.h = height; + } + } /** * @param heights: a matrix of integers * @return: an integer */ public int trapRainWater(int[][] heights) { - if (heights == null || heights.length == 0 || heights[0].length == 0) { - return 0; - } - - PriorityQueue queue = new PriorityQueue(1, new Comparator(){ - public int compare(Cell A, Cell B) { - return A.h - B.h; - } - }); - int n = heights.length; - int m = heights[0].length; - boolean[][] visited = new boolean[n][m]; - - //LEFT-RIGHT - for (int i = 0; i < n; i++) { - visited[i][0] = true; - visited[i][m - 1] = true; - queue.offer(new Cell(i, 0, heights[i][0])); - queue.offer(new Cell(i, m - 1, heights[i][m - 1])); - } - //TOP-BOTTOM - for (int i = 0; i < m; i++) { - visited[0][i] = true; - visited[n - 1][i] = true; - queue.offer(new Cell(0, i, heights[0][i])); - queue.offer(new Cell(n - 1, i, heights[n - 1][i])); - } - - int[] xs = {0, 0, 1, -1}; - int[] ys = {1, -1, 0, 0}; - int sum = 0; - while (!queue.isEmpty()) { - Cell cell = queue.poll(); - for (int i = 0; i < 4; i++) { - int nx = cell.x + xs[i]; - int ny = cell.y + ys[i]; - if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) { - visited[nx][ny] = true; - sum += Math.max(0, cell.h - heights[nx][ny]); - queue.offer(new Cell(nx, ny, Math.max(heights[nx][ny], cell.h))); - } - } - }//end while - return sum; + if (heights == null || heights.length == 0 || heights[0].length == 0) { + return 0; + } + + PriorityQueue queue = new PriorityQueue(1, new Comparator(){ + public int compare(Cell A, Cell B) { + return A.h - B.h; + } + }); + int n = heights.length; + int m = heights[0].length; + boolean[][] visited = new boolean[n][m]; + + //LEFT-RIGHT + for (int i = 0; i < n; i++) { + visited[i][0] = true; + visited[i][m - 1] = true; + queue.offer(new Cell(i, 0, heights[i][0])); + queue.offer(new Cell(i, m - 1, heights[i][m - 1])); + } + //TOP-BOTTOM + for (int i = 0; i < m; i++) { + visited[0][i] = true; + visited[n - 1][i] = true; + queue.offer(new Cell(0, i, heights[0][i])); + queue.offer(new Cell(n - 1, i, heights[n - 1][i])); + } + + int[] xs = {0, 0, 1, -1}; + int[] ys = {1, -1, 0, 0}; + int sum = 0; + while (!queue.isEmpty()) { + Cell cell = queue.poll(); + for (int i = 0; i < 4; i++) { + int nx = cell.x + xs[i]; + int ny = cell.y + ys[i]; + if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) { + visited[nx][ny] = true; + sum += Math.max(0, cell.h - heights[nx][ny]); + queue.offer(new Cell(nx, ny, Math.max(heights[nx][ny], cell.h))); + } + } + }//end while + return sum; } }; - - - - - - - - - - - - +``` \ No newline at end of file diff --git a/Java/Trapping Rain Water.java b/Java/Trapping Rain Water.java old mode 100644 new mode 100755 index cf83d97..bd593a2 --- a/Java/Trapping Rain Water.java +++ b/Java/Trapping Rain Water.java @@ -1,9 +1,14 @@ -2 Pointers, -双面夹击:找中间最大bar,两面往中心扫 +M + +2 Pointers, 双面夹击: +1. 找中间最高bar的index +2. 两面往中心扫:每次加上(topBarIndex - currIndex)* (elevation from previous index).也就是每次加一个横条。 +3. 每次还要减去block自身的height。 ``` /* -Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. +Given n non-negative integers representing an elevation map where the width of each bar is 1, +compute how much water it is able to trap after raining. Example Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. diff --git a/Java/Tweaked Identical Binary Tree.java b/Java/Tweaked Identical Binary Tree.java index cf00367..17c11c6 100644 --- a/Java/Tweaked Identical Binary Tree.java +++ b/Java/Tweaked Identical Binary Tree.java @@ -1,7 +1,12 @@ +E + +Recursive 比对左左,左右,右左,右右 + +``` /* -Check two given binary trees are identical or not. Assuming any number of tweaks are allowed. A tweak is defined as a swap of the children of one node in the tree. +Check two given binary trees are identical or not. Assuming any number of tweaks are allowed. +A tweak is defined as a swap of the children of one node in the tree. -Have you met this question in a real interview? Yes Example 1 1 / \ / \ @@ -28,10 +33,10 @@ */ /* - check isTweakedIdentical(a.left, b.right); + check isTweakedIdentical(a.left, b.right); - corner case: if both null, true; - if one null, false + corner case: if both null, true; + if one null, false */ /** * Definition of TreeNode: @@ -50,19 +55,18 @@ public class Solution { * @return true if they are tweaked identical, or false. */ public boolean isTweakedIdentical(TreeNode a, TreeNode b) { - if (a == null || b == null) { - return a == null && b == null; - } - if (a.val != b.val) { - return false; - } - return (isTweakedIdentical(a.left, b.left) && isTweakedIdentical(a.right, b.right)) - || (isTweakedIdentical(a.left, b.right) && isTweakedIdentical(a.right, b.left)); + if (a == null || b == null) { + return a == null && b == null; + } + if (a.val != b.val) { + return false; + } + return (isTweakedIdentical(a.left, b.left) && isTweakedIdentical(a.right, b.right)) + || (isTweakedIdentical(a.left, b.right) && isTweakedIdentical(a.right, b.left)); } } - - +``` \ No newline at end of file diff --git a/Java/Two Strings Are Anagrams.java b/Java/Two Strings Are Anagrams.java index 7ee5907..88b09b4 100644 --- a/Java/Two Strings Are Anagrams.java +++ b/Java/Two Strings Are Anagrams.java @@ -1,5 +1,11 @@ -Anagrams。 用count[256] +E + +方法1:char ascii 用count[256] 坑:不要想象这个是个26letter lowercase. may not be true. + +方法2: 若是其他字符encoding, 而不只是utf16-encoding (java char)? +那么就继续用string去做 + ``` /* Write a method anagram(s,t) to decide if two strings are anagrams or not. @@ -55,49 +61,43 @@ public boolean anagram(String s, String t) { }; - - - /* -Older version: -Thoughts: -1. s.charAt(i) is in t. -2. remove that char in t and s. -3. if at then all both are empty, return true. -NOTE: cannot use chararray to sort, because that takes O(n) space -BUG solved: when editing string, be careful with index. Index builds on original string length, -but string length changes over time. Solution: extra care on index, extra care on loop length change. +What if it's not just ascii code, maybe uni-code? +Then the character (utf16-encoding) may not be enough. So we use String here. */ + +//check length. compare public class Solution { - public boolean anagram(String s, String t) { - if (s == null || t == null || s.length() == 0 || t.length() == 0 || s.length() != t.length()) { + public boolean isAnagram(String s, String t) { + if (s == null || t == null || s.length() != t.length()) { return false; } if (s.equals(t)) { return true; } - int length = s.length(); - for (int i = 0; i < length; i++) { - int j = t.indexOf(s.charAt(0)); - if (j == -1) { - return false; + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + String ss = s.substring(i, i + 1); + String tt = t.substring(i, i + 1); + if (!map.containsKey(ss)) { + map.put(ss, 0); + } + map.put(ss, map.get(ss) + 1); + if (!map.containsKey(tt)) { + map.put(tt, 0); } - if (s.charAt(0) == t.charAt(j)) { - s = s.substring(1); - if (j == t.length() - 1) { - t = t.substring(0, j); - } else { - t = t.substring(0, j) + t.substring(j + 1); - } - } else { + map.put(tt, map.get(tt) - 1); + } + + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() != 0) { return false; } } - if (s.length() == 0 && t.length() == 0) { - return true; - } - return false; + + return true; } -}; +} + ``` \ No newline at end of file diff --git a/Java/Ugly Number II.java b/Java/Ugly Number II.java new file mode 100644 index 0000000..cbeae40 --- /dev/null +++ b/Java/Ugly Number II.java @@ -0,0 +1,76 @@ +非常brutle的。 +每次把dp[i-1]拿出来,不管三七二十一,分别乘以2,3,5. 出来的结果放进priority queue做比较。 +最后时间是n*log(n*3) + +注意: +Long +HashSet确保没有重复。 +``` +/* +Write a program to find the n-th ugly number. + +Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. +For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. + +Note that 1 is typically treated as an ugly number. +*/ + +/* + Thought: + Could do a infinite while loop, check each number see if that's an ugly number; till we find the nth. + time = m * O(avg # of factors for each integer) [m is probably a lot greater than n]~= O(m^2) + + So we definitely need to calculate it: + if we know a number x is ugly, we can *2, *3, *5 to make furture ugly numbers. + State: + dp[i]: ith ugly number. + fn: + candidate: Priority queue to hold candiates. + A HashSet() that makes sure dp[i-1]*2/3/5 is not duplicate. + candidate.add(dp[i - 1] * 2) + candidate.add(dp[i - 1] * 3) + candidate.add(dp[i - 1] * 5) + dp[i] = candidate.poll(); + init: + dp[0] = 0; + dp[1] = 1; + + return dp[n] + +Note: some number * 5 could be long. Just make sure it's long, then convert to int at the end. +*/ + +public class Solution { + public int nthUglyNumber(int n) { + if (n <= 0) { + return 0; + } else if (n == 1) { + return 1; + } + long[] dp = new long[n + 1]; + dp[0] = 0; + dp[1] = 1; + + PriorityQueue candidate = new PriorityQueue(); + HashSet set = new HashSet(); + set.add(dp[1]); + for (int i = 2; i <= n; i++) { + if (!set.contains(dp[i - 1] * 2)) { + candidate.add(dp[i - 1] * 2); + set.add(dp[i - 1] * 2); + } + if (!set.contains(dp[i - 1] * 3)) { + candidate.add(dp[i - 1] * 3); + set.add(dp[i - 1] * 3); + } + if (!set.contains(dp[i - 1] * 5)) { + candidate.add(dp[i - 1] * 5); + set.add(dp[i - 1] * 5); + } + dp[i] = candidate.poll(); + } + + return (int)dp[n]; + } +} +``` \ No newline at end of file diff --git a/Java/Ugly Number.java b/Java/Ugly Number.java index 026c1d7..9646254 100644 --- a/Java/Ugly Number.java +++ b/Java/Ugly Number.java @@ -1,3 +1,13 @@ +M + +方法1: PriorityQueue排序。用ArrayList check 新的ugly Number是否出现过。 + +方法1-1:(解释不通,不可取)用PriorityQueue排序。神奇的3,5,7走位:按照题目答案的出发,定了3,5,7以什么规律出现。但是题目并没有特殊表明。 + +方法2: DP . Not Done yet. + + +``` /* Ugly number is a number that only have factors 3, 5 and 7. @@ -12,6 +22,11 @@ Tags Expand LintCode Copyright Priority Queue + +*/ + +/* + Thoughts: Every level it's like: 3 5 7 @@ -25,7 +40,6 @@ Therefore, leave 3,5,7 cases till 7's . */ - class Solution { /** * @param k: The number k. @@ -57,7 +71,46 @@ public long kthPrimeNumber(int k) { } }; +//Ignore the sequence of 3, 5, 7. Use arraylist to check for duplicates +class Solution { + /** + * @param k: The number k. + * @return: The kth prime number as description. + */ + public long kthPrimeNumber(int k) { + if (k == 0) { + return 0; + } + ArrayList set = new ArrayList(); + PriorityQueue queue = new PriorityQueue(); + queue.offer((long)3); + queue.offer((long)5); + queue.offer((long)7); + set.add((long)3); + set.add((long)5); + set.add((long)7); + long num = 0; + for (int i = 0; i < k; i++) { + num = queue.poll(); + + if (!set.contains(num * 3)) { + queue.offer(num * 3); + set.add(num * 3); + } + if (!set.contains(num * 5)) { + queue.offer(num * 5); + set.add(num * 5); + } + if (!set.contains(num * 7)) { + queue.offer(num * 7); + set.add(num * 7); + } + } + return num; + } +}; /* Can use DP as well:http://blog.welkinlan.com/2015/07/28/ugly-number-lintcode-java/ -*/ \ No newline at end of file +*/ +``` \ No newline at end of file diff --git a/Java/Unique Path.java b/Java/Unique Path.java old mode 100644 new mode 100755 index 90e5be2..0193a28 --- a/Java/Unique Path.java +++ b/Java/Unique Path.java @@ -1,7 +1,11 @@ +M + +``` /* A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). -The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). +The robot can only move either down or right at any point in time. +The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). How many possible unique paths are there? @@ -9,15 +13,28 @@ m and n will be at most 100. Example -1,1 1,2 1,3 1,4 1,5 1,6 1,7 +1,1 1,2 1,3 1,4 1,5 1,6 1,7 2,1 -3,1 3,7 +3,1 3,7 Above is a 3 x 7 grid. How many possible unique paths are there? Tags Expand Array Dynamic Programming +*/ + +/* + 3.25.2016 recap + Regular DFS: each spot has 2 possible way out: right/down. We can count++ whenever we reach end. + This pattern seems to be DP: + Use a DP[i][j] to store: the # of possible paths to reach coordinate (i,j) + +*/ + + + +/* Thinking process: f[x][y]: want to find out all possible path To get to f[m][m] from f[m-1][n-1] has 2 way: f[m-1][n] or f[m][n-1]. @@ -27,7 +44,6 @@ Recursively add up to (0,0), will find out the total path. 1. Own solution: user HashMap to memorize */ - public class Solution { /** * @param n, m: positive integer (1 <= n ,m <= 100) @@ -81,7 +97,7 @@ public class Solution { * @param n, m: positive integer (1 <= n ,m <= 100) * @return an integer */ - //Traverse + //Traverse public int uniquePaths(int m, int n) { if (m <= 1 || n <= 1) { return 1; @@ -104,3 +120,5 @@ public int uniquePaths(int m, int n) { } } + +``` \ No newline at end of file diff --git a/Java/Unique Paths II.java b/Java/Unique Paths II.java old mode 100644 new mode 100755 diff --git a/Java/Unique Word Abbreviation.java b/Java/Unique Word Abbreviation.java new file mode 100644 index 0000000..f4a48f3 --- /dev/null +++ b/Java/Unique Word Abbreviation.java @@ -0,0 +1,91 @@ +/* +An abbreviation of a word follows the form . Below are some examples of word abbreviations: + +a) it --> it (no abbreviation) + + 1 +b) d|o|g --> d1g + + 1 1 1 + 1---5----0----5--8 +c) i|nternationalizatio|n --> i18n + + 1 + 1---5----0 +d) l|ocalizatio|n --> l10n +Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation. + +Example: +Given dictionary = [ "deer", "door", "cake", "card" ] + +isUnique("dear") -> false +isUnique("cart") -> true +isUnique("cane") -> false +isUnique("make") -> true + +Tags: Hash Table, Design +Similar Problems: (E) Two Sum III - Data structure design + + + +*/ +/* +Thought: +Originally, used a hashset to store all existing pattern. If checked word exist in dict hashset, then return false. +However, there is a case that: the word existed in the dict only for once, which is by accident the same as the checked work, then return true. +Therefore, we need to keep track of what word has been catagrize into pattern. SO, use a HashMap instead. + +Note: Dealing with char, integer, string. Be careful if char are turnning int integers. +*/ +public class ValidWordAbbr { + HashMap> map; + public ValidWordAbbr(String[] dict) { + if (dict == null || dict.length == 0) { + return; + } + map = new HashMap>(); + for (String s : dict) { + String str = ""; + if (s.length() <= 2) { + str = s; + } else { + str += s.charAt(0) + (s.length() - 2 + "") + s.charAt(s.length() - 1); + } + if (!map.containsKey(str)) { + ArrayList list = new ArrayList(); + list.add(s); + map.put(str, list); + } else { + if (!map.get(str).contains(s)) { + map.get(str).add(s); + } + + } + } + } + + public boolean isUnique(String word) { + if (map == null || map.size() == 0) { + return true; + } + String str = ""; + if (word.length() <= 2) { + str = word; + } else { + str += word.charAt(0) + (word.length() - 2 + "") + word.charAt(word.length() - 1); + } + if (map.containsKey(str) && map.get(str).size() == 1 && map.get(str).get(0).equals(word)) { + return true; + } + return !map.containsKey(str); + } +} + + + + + +// Your ValidWordAbbr object will be instantiated and called as such: +// ValidWordAbbr vwa = new ValidWordAbbr(dictionary); +// vwa.isUnique("Word"); +// vwa.isUnique("anotherWord"); \ No newline at end of file diff --git a/Java/Valid Anagram.java b/Java/Valid Anagram.java new file mode 100644 index 0000000..177b324 --- /dev/null +++ b/Java/Valid Anagram.java @@ -0,0 +1,58 @@ +/* +Given two strings s and t, write a function to determine if t is an anagram of s. + +For example, +s = "anagram", t = "nagaram", return true. +s = "rat", t = "car", return false. + +Note: +You may assume the string contains only lowercase alphabets. + +Follow up: +What if the inputs contain unicode characters? How would you adapt your solution to such case? + +Tags: Hash Table, Sort +Similar Problems: (M) Group Anagrams, (E) Palindrome Permutation + + +*/ +/* +Thoughts: +Anagram: reorder of letters. +Use HashMap to store the frequency of chars of 1st string, and check aginst 2nd string. +s character: +1; +t character: -1; +check count of each index in the map; they should all be 0 +*/ + + +public class Solution { + public boolean isAnagram(String s, String t) { + if (s == null || t == null) { + return s == null && t == null; + } else if (s.length() != t.length()) { + return false; + } + + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + if (!map.containsKey(s.charAt(i))) { + map.put(s.charAt(i), 1); + } else { + map.put(s.charAt(i), map.get(s.charAt(i)) + 1); + } + if (!map.containsKey(t.charAt(i))) { + map.put(t.charAt(i), -1); + } else { + map.put(t.charAt(i), map.get(t.charAt(i)) - 1); + } + }//END for + + for (int i = 0; i < s.length(); i++) { + if (map.get(s.charAt(i)) != 0) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Java/Valid Palindrome.java b/Java/Valid Palindrome.java old mode 100644 new mode 100755 index 88a81a9..ffeed0a --- a/Java/Valid Palindrome.java +++ b/Java/Valid Palindrome.java @@ -1,4 +1,8 @@ -注意如何滤过: alphanumeric +E +tutorial:https://www.youtube.com/watch?v=2hNK0Yz53LQ&list=PLZn-UvluQZuNedn1hDzTmNLE8MQWXjKVb + +过滤alphanumeric,其他字母掠过 + ``` /* Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. @@ -16,9 +20,69 @@ Challenge O(n) time without extra memory. -Tags Expand -String Two Pointers +Company: Microsoft Uber Facebook Zenefits +Hide Tags Two Pointers String +Hide Similar Problems (E) Palindrome Linked List + + +*/ +/* +recap: +Use regular expression [^a-zA-Z0-9] to replace all non-alphanumeric chars with "" */ +public class Solution { + public boolean isPalindrome(String s) { + if (s == null || s.length() <= 1) { + return true; + } + final String str = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase(); + int start = 0; + int end = str.length() - 1; + while (start < end) { + if (str.charAt(start) != str.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } +} + +/* +3.4.2016 recap +Filter the String first, then check Palindrome +But uses extra space to filter the string. Can also just manipulate string on itself. no big deal +*/ + +public class Solution { + public boolean isPalindrome(String s) { + if (s == null || s.length() == 0) { + return true; + } + + StringBuffer sb = new StringBuffer(); + s = s.toLowerCase(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if ((c <= 'z' && c >= 'a') || (c >= '0' && c <= '9')) { + sb.append(s.charAt(i)); + } + } + s = sb.toString(); + int start = 0; + int end = s.length() - 1; + while (start < end) { + if (s.charAt(start) != s.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } +} + /* Thoughts: Pointer from front to end. Front char has to equal end char. diff --git a/Java/Valid Parentheses.java b/Java/Valid Parentheses.java index ef8e128..8dd1ded 100644 --- a/Java/Valid Parentheses.java +++ b/Java/Valid Parentheses.java @@ -1,6 +1,11 @@ -剥皮形态。 -左边的外皮在stack底部。 -右边的外皮应该和最顶上的左外皮一一对应。 +E + +剥皮过程。解铃还须系铃人 +左边的外皮'{['在stack底部 +右边的外皮应该和stack顶上的左外皮一一对应 + + + ``` /* Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. @@ -12,6 +17,47 @@ Stack */ +//02.04.2015 Recap +//lock will be unlocked by the same key +//put in stack. when '),],}' appears, check stack.top() to make sure they are good match +public class Solution { + public boolean isValid(String s) { + if (s == null || s.length() == 0) { + return true; + } + if (s.length() % 2 != 0) { + return false; + } + Stack stack = new Stack(); + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } else if (c ==')' || c == ']' || c == '}') { + if (stack.isEmpty()) { + return false; + } + char front = stack.pop(); + if (c == ')' && front != '(') { + return false; + } + if (c == ']' && front != '[') { + return false; + } + if (c == '}' && front != '{') { + return false; + } + } else { + return false; + } + } + + return stack.isEmpty(); + } +} + + /* Thoughts: Did this on Leetcode. Think about how do we naturally check it? diff --git a/Java/Valid Sudoku.java b/Java/Valid Sudoku.java index 4988597..4ddf43f 100644 --- a/Java/Valid Sudoku.java +++ b/Java/Valid Sudoku.java @@ -1,5 +1,13 @@ -好像没啥技术含量. 做就行了。 -validate block的时候虽然看到了4层for.其实也就是n^2. +E + +用HashSet存visited value. + +方法1: 在nest for loop里面validate row,col,and block. +validate block要利用i 和 j 增长的规律。 +说白了,i && j是按照0~n增长的index, 具体怎么用是可以flexible的。这个方法在同一个nest for loop解决所有运算。 + +方法2: 单独做block validation: validate block的时候虽然看到了4层for.其实也就是n^2. + ``` /* Determine whether a Sudoku is valid. @@ -26,6 +34,48 @@ A valid Sudoku board (partially filled) is not necessarily solvable. Only the fi Matrix */ +/*Recap 3.7.2016 */ +class Solution { + public boolean isValidSudoku(char[][] board) { + if (board == null || board.length == 0 || board[0].length == 0 || board.length != board[0].length) { + return false; + } + HashSet row,col,block; + int n = board.length; + + for (int i = 0; i < n; i++) { + row = new HashSet(); + col = new HashSet(); + block = new HashSet(); + for (int j = 0; j < n; j++) { + //Check row + if (!row.contains(board[i][j])) { + row.add(board[i][j]); + } else if (board[i][j] != '.'){ + return false; + } + //Check col + if (!col.contains(board[j][i])) { + col.add(board[j][i]); + } else if (board[j][i] != '.'){ + return false; + } + //check block + int c = j % 3 + 3 * (i % 3);//make use of how i and j increases + int r = j / 3 + 3 * (i / 3); + if (!block.contains(board[r][c])) { + block.add(board[r][c]); + } else if (board[r][c] != '.') { + return false; + } + } + } + + return true; + } +}; + + /* Thoughts: Each row/col/block can only 1 ~ 9, no duplicates @@ -35,10 +85,6 @@ A valid Sudoku board (partially filled) is not necessarily solvable. Only the fi */ class Solution { - /** - * @param board: the board - @return: wether the Sudoku is valid - */ public boolean isValidSudoku(char[][] board) { if (board == null || board.length == 0 || board[0].length == 0 || board.length != board[0].length) { return false; diff --git a/Java/Validate Binary Search Tree.java b/Java/Validate Binary Search Tree.java old mode 100644 new mode 100755 index 21cfec4..e3934b0 --- a/Java/Validate Binary Search Tree.java +++ b/Java/Validate Binary Search Tree.java @@ -1,5 +1,10 @@ +M + +查看每个parent-child关系。同时把root level上面传下来max,min界限定住。 + +``` + /* -29% Accepted Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: @@ -7,25 +12,21 @@ Given a binary tree, determine if it is a valid binary search tree (BST). The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys greater than the node's key. Both the left and right subtrees must also be binary search trees. -Example -An example: +A single node tree is a BST + +Example: - 1 - / \ - 2 3 - / - 4 - \ - 5 -The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}". + 2 + / \ +1 4 + / \ + 3 5 +The above binary tree is serialized as {2,1,4,#,#,3,5} (in level order). Tags Expand -Tree Binary Tree Binary Search Tree +Divide and Conquer Recursion Binary Search Tree Binary Tree + -Thinking process: -Need to go through every node. -Need to determine parent node’s relationship with left/right child. -Then reminds me of Divide and Conquer. */ /** @@ -39,26 +40,35 @@ Given a binary tree, determine if it is a valid binary search tree (BST). * } * } */ + +//recursively check if tree are BST, && them all + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ public class Solution { - /** - * @param root: The root of binary tree. - * @return: True if the binary tree is BST, or false - */ public boolean isValidBST(TreeNode root) { + return helper(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean helper(TreeNode root, long min, long max) { if (root == null) { return true; } - if (root.left != null && root.left.val >= root.val) { - return false; - } - if (root.right != null && root.right.val <= root.val) { - return false; - } - - boolean left = isValidBST(root.left); - boolean right = isValidBST(root.right); - - return left && right; + if (root.val < max && root.val > min && + helper(root.left, min, root.val) && + helper(root.right, root.val, max)) { + return true; + } + return false; } } + +``` \ No newline at end of file diff --git a/Java/Wiggle Sort.java b/Java/Wiggle Sort.java new file mode 100644 index 0000000..b467cbc --- /dev/null +++ b/Java/Wiggle Sort.java @@ -0,0 +1,92 @@ +第一遍想太多. 其实做一个fall-through就能把问题解决,原因是因为: +这样的fall-through每次在乎两个element,可以一口气搞定,无关乎再之前的elements。 +特别的一点:flag来巧妙的掌控山峰和低谷的变化。又是神奇的一幕啊! + +这样子的奇观,见过就要知道了,没见过的时候有点摸不着头脑。 +``` +/* +Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3].... + +For example, given nums = [3, 5, 2, 1, 6, 4], one possible answer is [1, 6, 2, 5, 3, 4]. + +Tags: Array Sort +Similar Problems: (M) Sort Colors + +*/ + +/* +Attemp2, Thoughts: (http://www.cnblogs.com/easonliu/p/4798814.html) +Draw wiggle on original array. Whenever any postion i is not working with i-1, swap them. +Cases: +1. when nums[i] is supposed to >= nums[i - 1], however it's nums[i] < nums[i - 1], swap them. For example (nums[1] vs. nums[0]) +2. when nums[i] is supposed to <= nums[i - 1], however it's nums[i] > nums[i - 1], swap them. For example (nums[2] vs. nums[1]) +Specially, for case 2: can times a -1 on both side, to make nums[i] * -1 < nums[i - 1] * -1. Therefore we only need 1 if statement. + +Concept: whenver something does not work, fix it. (especailly now we are only taking caer of 2 elements at a time, so we can do it as a fall-through) +*/ +public class Solution { + public void wiggleSort(int[] nums) { + if (nums == null || nums.length <= 1) { + return; + } + int flag = 1; + for (int i = 1; i < nums.length; i++) { + if (flag * nums[i] < flag * nums[i - 1]) { + swap(nums, i, i - 1); + } + flag = -1 * flag; + } + } + + public void swap(int[] nums, int x, int y) { + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } +} + + +/* +Attempt1: +Wiggle sort, ofcourse can't do Arrays.sort()! Should sort in one pass. +Also, we don't need to make each wiggle elements in ascending order (1,(4),2,(5),3,(6) ... etc). I thought it over. +---- +List out the example of 1,2,3,4,5,6,7,8, want to move (5,6,7,8) and insert between (1,2,3,4). It follows the follows patter: +Assume total length = n, and we are moving index i = (1 ~ n) +Step1: swap (n + i)/2, and i, (where initially i == 1) +Step2: swap (n + i)/2, and i+1 +Step2: i+=2; + + +public class Solution { + public void wiggleSort(int[] nums) { + if (nums == null || nums.length == 0) { + return; + } + Arrays.sort(nums); + if (nums.length <= 2) { + return; + } + int leng = nums.length; + int ind1 = 0; + int ind2 = 0 + for (int i = 1; i < leng; i++) { + //Step1 + ind1 = (leng + i) / 2; + ind2 = i; + swap(ind1, ind2); + //Step2: + ind2 = i + 1; + swap(ind1, ind2); + } + } + + public void swap(int[] nums, int x, int y) { + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } +} +*/ + +``` \ No newline at end of file diff --git a/Java/Word Break II.java b/Java/Word Break II.java new file mode 100755 index 0000000..2029e3a --- /dev/null +++ b/Java/Word Break II.java @@ -0,0 +1,146 @@ +H + +两个DP一起用.解决了timeout的问题 +1. isWord[i][j], subString(i,j)是否存在dict中? + +2. 用isWord加快 isValid[i]: [i ~ end]是否可以从dict中找到合理的解? + 从末尾开始查看i:因为我们需要测试isWord[i][j]时候,j>i, 而我们观察的是[i,j]这区间; + j>i的部分同样需要考虑,我们还需要知道isValid[0~j+1]。 所以isValid[x]这次是表示[x, end]是否valid的DP。 + i 从 末尾到0, 可能是因为考虑到isWord[i][j]都是在[0~n]之内,所以倒过来数,坐标比较容易搞清楚。 + (回头看Word Break I, 也有坐标反转的做法) + +3. dfs 利用 isValid 和isWord做普通的DFS。 + +Note: +在Word Break里面用了set.contains(...), 在isValid里面,i 从0开始。 但是,contains()本身是O(n). +在这道题里面应该是因为word dictionary太大,加上nest for, 变成O(n^3)所以timeout. + +istead,用一个isWord[i][j],就O(1)判断了i~j是不是存在dictionary里面。 + +``` +/* +Given a string s and a dictionary of words dict, add spaces in s to construct a sentence +where each word is a valid dictionary word. + +Return all such possible sentences. + +For example, given +s = "catsanddog", +dict = ["cat", "cats", "and", "sand", "dog"]. + +A solution is ["cats and dog", "cat sand dog"]. + +Hide Company Tags Google Uber +Hide Tags Dynamic Programming Backtracking + +*/ +/* + Thoughts: DP + Check if s.substring(i,j) is a valid word + state: isWord[i][j] + function: isWord[i][j] = set.contains(s.substring(i, j + 1)); + + Check if postFixed string is valid solution isValid[j]: [j+1, end] inclusive is valid or no? + state: isValid[i] + function: similar to in Word Break I + + DFS: + if isValid(i), and isWord(i,j) then go deeper +*/ + +public class Solution { + public List wordBreak(String s, Set wordDict) { + List rst = new ArrayList(); + if (s == null || s.length() == 0 || wordDict == null || wordDict.size() == 0) { + return rst; + } + + boolean[][] isWord = validateWord(s, wordDict); + boolean[] isValid = validatePossibility(s, wordDict, isWord); + + dfs(rst, new ArrayList(), s, 0, isValid, isWord, wordDict); + return rst; + } + + public void dfs(List rst, ArrayList list, String s, + int index, boolean[] isValid, boolean[][] isWord, Set set) { + if (!isValid[index]) { + return; + } + //output + if (index >= s.length()) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size(); i++) { + sb.append(list.get(i)); + if (i != list.size() - 1) { + sb.append(" "); + } + } + rst.add(sb.toString()); + return; + } + //dfs + for (int i = index; i < s.length(); i++) { + if (!isWord[index][i]) { + continue; + } + + list.add(s.substring(index, i + 1)); + dfs(rst, list, s, i + 1, isValid, isWord, set); + list.remove(list.size() - 1); + } + } + + //dp[i][j] check if s.substring(i,j) is a proper word from dictionary + public boolean[][] validateWord(String s, Set set) { + boolean[][] isWord = new boolean[s.length()][s.length()]; + for (int i = 0; i < s.length(); i++) { + for (int j = i; j < s.length(); j++) { + isWord[i][j] = set.contains(s.substring(i, j + 1)); + } + } + return isWord; + } + + //Build the validation boolean[] + public boolean[] validatePossibility(String s, Set set, boolean[][] isWord) { + /* + boolean[] valid = new boolean[s.length() + 1]; + valid[s.length()] = true; + + int maxLeng = getMaxLength(set); + for (int i = s.length() - 1; i >= 0; i--) { + for (int j = i; j < s.length() && (j - i) <= maxLeng; j++) { + if (isWord[i][j] && valid[j + 1]) { + valid[i] = true; + break; + } + } + }*/ + boolean[] valid = new boolean[s.length() + 1]; + valid[0] = true; + int maxLength = getMaxLength(set); + for (int i = 0; i < s.length(); i++) { + for (int j = 0; j < i && j < maxLength; j++) {//iterate [0 ~ i] + if (isWord[i - j][i] && isValid[i - j + 1])) { + valid[i + 1] = true; + break; + } + } + } + + return valid; + } + + //Get max length, a little optimization + public int getMaxLength(Set dict) { + int length = 0; + for (String word : dict) { + length = Math.max(length, word.length()); + } + return length; + } +} + + +``` \ No newline at end of file diff --git a/Java/Word Break.java b/Java/Word Break.java old mode 100644 new mode 100755 index 1ff9ff8..fa9325d --- a/Java/Word Break.java +++ b/Java/Word Break.java @@ -1,5 +1,23 @@ +M + +DP + +方法1:(attempt3 code) +state,rst[i]: 从[0~i] inclusive的string是否可以在dict中break开来找到? +function: rst[i] = true if (rst[i - j] && set.contains(s.substring(i - j, i))); j in[0~i] +1. rst[i - j] 记录的是[0, i-j]这一段是否可以break后在dict找到。 +2. 若true,再加上剩下所有[i-j, i]都能在dict找到,那么rst[i] = rst[0, i - j] && rst[i-j, i] == true + +优化:找dict里面最长string, 限制j的增大。 + +(attempt4 code) +与Word BreakII用同样的DP。 +valid[i]: 记录从i到valid array末尾是否valid. + +``` /* -Given a string s and a dictionary of words dict, determine if s can be break into a space-separated sequence of one or more dictionary words. +Given a string s and a dictionary of words dict, determine if s can be break into a space-separated +sequence of one or more dictionary words. Example Given s = "lintcode", dict = ["lint", "code"]. @@ -11,8 +29,45 @@ */ /* -Attemp3: -Optimize attempt2: If the input s is super long, but Dict does not have that long string, then we should avoid that case, so to save time. That is, check dict's strings' max length, and incldue that in 2nd-level for loop +Attempt4: same as attempt3, but reversed how to build the validation matrix. (Same style as in Word Break II) +valid[i]: 从i 到valid.length末尾是否valid +*/ +public class Solution { + public boolean wordBreak(String s, Set dict) { + if (s == null || dict.contains(s)) { + return true; + } + + boolean[] valid = new boolean[s.length() + 1]; + valid[s.length()] = true; + int maxLength = calMaxLength(dict); + for (int i = s.length() - 1; i >= 0; i--) { + for (int j = i; j < s.length() && (i - j) <= maxLength; j++) {//iterate [0 ~ i] + if (valid[j + 1] && dict.contains(s.substring(i, j + 1))) { + valid[i] = true; + break; + } + } + } + + return valid[0]; + } + + public int calMaxLength(Set dict) { + int length = 0; + for (String word : dict) { + length = Math.max(length, word.length()); + } + return length; + } +} + + +/* +Attempt3: +Optimize attempt2: If the input s is super long, but Dict does not have that long string, +then we should avoid that case, so to save time. That is, check dict's strings' max length, +and incldue that in 2nd-level for loop j: last word's length, range from 0 to i. [i - j]: the first index of current word @@ -28,17 +83,33 @@ public boolean wordBreak(String s, Set dict) { if (s == null || dict.contains(s)) { return true; } + +/* boolean[] rst = new boolean[s.length() + 1]; rst[0] = true; int maxLength = calMaxLength(dict); for (int i = 0; i <= s.length(); i++) { - for (int j = 0; j <= i && j <= maxLength; j++) { + for (int j = 0; j <= i && j <= maxLength; j++) {//iterate [0 ~ i] if (rst[i - j] && dict.contains(s.substring(i - j, i))) { rst[i] = true; break; } } } + +*/ + boolean[] rst = new boolean[s.length() + 1]; + rst[s.length()] = true; + int maxLength = calMaxLength(dict); + for (int i = s.length() - 1; i >= 0; i--) { + for (int j = i; j < s.length() && (i - j) <= maxLength; j++) {//iterate [0 ~ i] + if (rst[i + 1] && dict.contains(s.substring(i, j))) { + rst[i] = true; + break; + } + } + } + return rst[s.length()]; } @@ -54,34 +125,65 @@ public int calMaxLength(Set dict) { /* +DP Attemp2, Thought: Use boolena to denote rst[i]: s[0,i-1] can be break to match dict. For the ease to explain, let's consider rst[i+1] with actually string s[0,i]; How to calculate rst[i+1]? - As long as there is at least 1 way to break s[0, i], that would work. so do a for loop to check on string s[0, i]: - For each i, use another index j, j = 0 ~ i. If rst[j] works and s[j,i+1] is in dict, that makes rst[i+1] = true. + As long as there is at least 1 way to break s[0, i], that would work. so do a for loop to check on string s[0, i]: + For each i, use another index j, j = 0 ~ i. If rst[j] works and s[j,i+1] is in dict, that makes rst[i+1] = true. Correct: however excceeds time limit at 97% correct */ public class Solution { public boolean wordBreak(String s, Set dict) { - if (s == null || dict.contains(s)) { - return true; - } - boolean[] rst = new boolean[s.length() + 1]; - rst[0] = true; - for (int i = 0; i < s.length(); i++) { - for (int j = 0; j <= i; j++) { - if (rst[j] && dict.contains(s.substring(j, i + 1))) { - rst[i + 1] = true; - break; - } - } - } - return rst[s.length()]; + if (s == null || dict.contains(s)) { + return true; + } + boolean[] rst = new boolean[s.length() + 1]; + rst[0] = true; + for (int i = 0; i < s.length(); i++) { + for (int j = 0; j <= i; j++) { + if (rst[j] && dict.contains(s.substring(j, i + 1))) { + rst[i + 1] = true; + break; + } + } + } + return rst[s.length()]; } } +//Timeout, DFS +//Break the word into pieces: recursively break using start,end pointer. +//End pointer always moves forward, but start pointer may not. +public class Solution { + public boolean wordBreak(String s, Set wordDict) { + if (s == null || s.length() == 0 || wordDict == null || wordDict.size() == 0) { + return false; + } + + return helper(s, wordDict, 0, 0); + } + public boolean helper(String s, Set set, int start, int end) { + if (end == s.length() - 1) { + if (start == end) { + return true; + } + return set.contains(s.substring(start)); + } + //no break + boolean noBreak = helper(s, set, start, end + 1); + + //break: + boolean hasBreak = false; + if (set.contains(s.substring(start, end + 1))) { + hasBreak = helper(s, set, end + 1, end + 1); + } + + return noBreak || hasBreak; + } +} @@ -91,4 +193,5 @@ public boolean wordBreak(String s, Set dict) { Create DP[i][j] based on dict that says: combine i number of dict strings and j number of dict strings, do we have a combined string that contains the target? However, this seems confusing and over-complex. We only have 1 set of variables: dict, so maybe it's now wise to create 2D DP[][]. -*/ \ No newline at end of file +*/ +``` diff --git a/Java/Word Ladder II.java b/Java/Word Ladder II.java index 8a38c03..4b511de 100644 --- a/Java/Word Ladder II.java +++ b/Java/Word Ladder II.java @@ -1,9 +1,14 @@ +H + +``` + /* -Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: +Given two words (start and end), and a dictionary, +find all shortest transformation sequence(s) from start to end, such that: Only one letter can be changed at a time Each intermediate word must exist in the dictionary -Have you met this question in a real interview? Yes + Example Given: start = "hit" @@ -126,8 +131,8 @@ public ArrayList expand(String str, Set dict) { //2. If use StringBuffer strCheck to check if particular sequence exist, then exceed time limit. //It looks like we'd use DFS for final results. public class Solution { - private Queue q = new LinkedList(); - private Queue> backtrackList = new LinkedList>(); + private Queue q = new LinkedList(); + private Queue> backtrackList = new LinkedList>(); private Set dict; private String end; private int level = 1; @@ -136,58 +141,58 @@ public class Solution { public List> findLadders(String start, String end, Set dict) { if (start == null || end == null || dict == null || start.length() != end.length()) { - return rst; - } - this.dict = dict; - this.end = end; - ArrayList head = new ArrayList(); - head.add(start); - q.offer(start); - backtrackList.offer(head); - while(!q.isEmpty()) {//BFS - int size = q.size();//Fix size - level++; - for (int k = 0; k < size; k++) {//LOOP through existing queue: for this specific level - String str = q.poll(); - ArrayList list = backtrackList.poll(); - validateMutations(str, list); - }//END FOR K - }//END WHILE + return rst; + } + this.dict = dict; + this.end = end; + ArrayList head = new ArrayList(); + head.add(start); + q.offer(start); + backtrackList.offer(head); + while(!q.isEmpty()) {//BFS + int size = q.size();//Fix size + level++; + for (int k = 0; k < size; k++) {//LOOP through existing queue: for this specific level + String str = q.poll(); + ArrayList list = backtrackList.poll(); + validateMutations(str, list); + }//END FOR K + }//END WHILE - List> minRst = new ArrayList>(); - for (int i = 0; i < rst.size(); i++) { - if (rst.get(i).size() == len) { - minRst.add(rst.get(i)); - } - } - return minRst; + List> minRst = new ArrayList>(); + for (int i = 0; i < rst.size(); i++) { + if (rst.get(i).size() == len) { + minRst.add(rst.get(i)); + } + } + return minRst; } public void validateMutations(String str, ArrayList list) { - if (list.size() > len) {//No need to digger further if list is already greater than min length - return; - } - for (int i = 0; i < str.length(); i++) {//Alternate each letter position - for (int j = 0; j < 26; j++) {//Alter 26 letters + if (list.size() > len) {//No need to digger further if list is already greater than min length + return; + } + for (int i = 0; i < str.length(); i++) {//Alternate each letter position + for (int j = 0; j < 26; j++) {//Alter 26 letters if (str.charAt(i) == (char)('a' + j)) { continue; } - String newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); + String newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); - ArrayList temp = (ArrayList)list.clone(); - temp.add(newStr); - if (dict.contains(newStr)) { - if (newStr.equals(end)) {//Found end - len = Math.min(len, level); - rst.add(temp); - } else { - q.offer(newStr); - backtrackList.offer(temp); - } - } - }//END FOR J - }//END FOR I + ArrayList temp = (ArrayList)list.clone(); + temp.add(newStr); + if (dict.contains(newStr)) { + if (newStr.equals(end)) {//Found end + len = Math.min(len, level); + rst.add(temp); + } else { + q.offer(newStr); + backtrackList.offer(temp); + } + } + }//END FOR J + }//END FOR I } } @@ -277,4 +282,5 @@ List expand(String crt, Set dict) { } -*/ \ No newline at end of file +*/ +``` \ No newline at end of file diff --git a/Java/Word Ladder.java b/Java/Word Ladder.java index d15adbf..1f7cfec 100644 --- a/Java/Word Ladder.java +++ b/Java/Word Ladder.java @@ -1,5 +1,14 @@ +M + +BFS Brutle: 在start string基础上,string的每个字母都遍历所有26个字母,换换。 + +方法2: +用Trie。 理应更快. However implementation可能有点重复计算的地方,LeetCode timeout. 需要再做做。 + +``` /* -Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that: +Given two words (start and end), and a dictionary, +find the length of shortest transformation sequence from start to end, such that: Only one letter can be changed at a time Each intermediate word must exist in the dictionary @@ -20,7 +29,8 @@ Given two words (start and end), and a dictionary, find the length of shortest t Breadth First Search Thoughts: -Use the dict (check if mutation exist in dict) as base to create a directed graph, use BFS to find shortest path. +Use the dict (check if mutation exist in dict) as base to create a directed graph, +use BFS to find shortest path. Note: Be careful with queue size when trying to do for loop on it. Use a pre-fixed size = q.size(), in case queue's size changes during for loop. @@ -124,3 +134,183 @@ else if (i == str.length() - 1) { }//END FOR I } } + + + + + + + +/* + Use a new method in Trie: + getChildrenMap(string s): get the children hashmap at last char of s. + getCurrMap(s): get the hashmap where the last char of s is at. + + However, still timeout in LeetCode. So there might be some case that's using extra calculation. + It should ideally be faster than brutle force. +*/ +import java.io.*; +import java.util.*; + +class Solution { + + class TrieNode { + String str; + boolean isEnd; + boolean visited; + HashMap children; + public TrieNode () { + this.isEnd = false; + this.visited = false; + this.str = ""; + children = new HashMap(); + } + } + + + + public TrieNode root = new TrieNode(); + public int leng = Integer.MAX_VALUE; + public int ladderLength(String beginWord, String endWord, Set wordList) { + if (beginWord == null || endWord == null || beginWord.length() != endWord.length() + || wordList == null || wordList.size() == 0) { + return 0; + } + + //build Trie + for (String s : wordList) { + insert(s); + } + dfs(beginWord, endWord, 1); + + return leng; + } + + public void dfs(String start, String end, int step) { + if (step >= leng) { + return; + } + + if (compare(start, end) == 0) { + leng = Math.min(leng, step); + return; + } + //catch last step, so it covers the case where last change is not in dictionary + if (compare(start, end) == 1) { + leng = Math.min(leng, step + 1); + return; + } + + for (int i = 0; i < start.length(); i++) {//try to replace every index + String s = start.substring(0, i + 1); + HashMap candidates = getCurrentMap(s); + + //If char(i) not in dictinary, go back up one level, + //try to find all possible children candidates of previous char. Keep going with the process + if (candidates == null) { + s = start.substring(0, i); + candidates = getChildrenMap(s); + //If prev char is not found neither, fail it. + //Example, when 'b' in "ab" not found, try to find 'a' and its children; however, if 'a' not found neither, cut it off here + if (candidates == null) { + continue; + } + } + + //Replace char at i with all candidates existing in Trie dictionary + for (Map.Entry entry : candidates.entrySet()) { + char c = entry.getKey(); + String newStr = start.substring(0,i) + c + start.substring(i+1); + if (c != start.charAt(i) && !entry.getValue().visited) { + candidates.get(c).visited = true; + dfs(newStr, end, step + 1); + } + } + } + } + + /**************************Trie section *********************/ + //In this problem ,didin't use startWith() or search(). + //Instead, use a similar function, getChildrenMap. See below + + public void insert (String s){ + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + node.children.put(c, new TrieNode()); + } + node = node.children.get(c); + if (i == arr.length - 1) { + node.isEnd = true; + node.str = s; + } + } + } + + /*Return the HashMap where the last char of s is in*/ + public HashMap getCurrentMap(String s) { + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + return null; + } + if (i == arr.length - 1) { + return node.children; + } + node = node.children.get(c); + } + return null; + } + + /*Return the children HashMap of the last char*/ + public HashMap getChildrenMap(String s) { + if (s == null || s.length() == 0) { + return root.children; + } + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + return null; + } + node = node.children.get(c); + } + return node.children; + } + + //Helper to comapre string and return the difference if not <= 1 + public int compare(String s1, String s2) { + int count = 0; + for (int i = 0; i < s1.length(); i++) { + count += s1.charAt(i) != s2.charAt(i) ? 1 : 0; + if (count > 1) { + return count; + } + } + return count; + } + + + public static void main(String[] args) { + String beginWord = "hit";//"hit"; + String endWord = "cog"; + Set set = new HashSet(); + set.add("hot"); set.add("dot"); set.add("dog"); set.add("lot"); set.add("log"); + + + Solution sol = new Solution(); + int leng = sol.ladderLength(beginWord, endWord, set); + + System.out.println("rst " + leng ); + System.out.println("END"); + } + +} + + +``` \ No newline at end of file diff --git a/Java/Word Pattern.java b/Java/Word Pattern.java new file mode 100644 index 0000000..e77f017 --- /dev/null +++ b/Java/Word Pattern.java @@ -0,0 +1,105 @@ +E + +每个char代表一个pattern。用HashMap. +但不够,如果a也match dog, b也match dog, 纠错了。比如pattern = "abba", str = "dog dog dog dog"。 +因此第二个HashMap 反过来。 +确保pattern和str一一对应。 + +``` +/* +Given a pattern and a string str, find if str follows the same pattern. + +Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str. + +Examples: +pattern = "abba", str = "dog cat cat dog" should return true. +pattern = "abba", str = "dog cat cat fish" should return false. +pattern = "aaaa", str = "dog cat cat dog" should return false. +pattern = "abba", str = "dog dog dog dog" should return false. +Notes: +You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space. + +Credits: +Special thanks to @minglotus6 for adding this problem and creating all test cases. + +Hide Company Tags Dropbox +Hide Tags Hash Table +Hide Similar Problems (E) Isomorphic Strings (H) Word Pattern II + +*/ + +/* + 3.1.2016 recap. + HashMap, one to one mapping +*/ +public class Solution { + public boolean wordPattern(String pattern, String str) { + if (pattern == null || pattern.length() == 0 || str == null || str.length() == 0) { + return false; + } + + String[] strArr = str.split(" "); + if (pattern.length() != strArr.length) { + return false; + } + HashMap map = new HashMap(); + + for (int i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + String s = strArr[i]; + if (!map.containsKey(c)) { + if (map.containsValue(s)) { + return false; + } + map.put(c, s); + } else if (!map.get(c).equals(s)) { + return false; + } + } + return true; + } +} + + +/* +Thoughts: +2 HashMap, HashMap double check +*/ +public class Solution { + public boolean wordPattern(String pattern, String str) { + if (pattern != null && str != null && pattern.length() == 0 && str.length() == 0) { + return true; + } + if (pattern == null || pattern.length() == 0 || str == null || str.length() == 0) { + return false; + } + String[] strArr = str.split(" "); + if (pattern.length() != strArr.length) { + return false; + } + + HashMap map = new HashMap(); + HashMap mapStr = new HashMap(); + + for (int i = 0; i < strArr.length; i++){ + if (!map.containsKey(pattern.charAt(i))) { + map.put(pattern.charAt(i), strArr[i]); + } else { + if (!map.get(pattern.charAt(i)).equals(strArr[i])) { + return false; + } + } + if (!mapStr.containsKey(strArr[i])) { + mapStr.put(strArr[i], pattern.charAt(i)); + } else { + if (mapStr.get(strArr[i]) != pattern.charAt(i)) { + return false; + } + } + } + return true; + } +} + + +``` \ No newline at end of file diff --git a/Java/Word Search II.java b/Java/Word Search II.java old mode 100644 new mode 100755 index 30f77a3..7454271 --- a/Java/Word Search II.java +++ b/Java/Word Search II.java @@ -1,3 +1,26 @@ +H + +Big improvement: use boolean visited on TrieNode! +不要用rst.contains(...), 因为这个是O(n) 在leetcode还是会timeout(lintcode竟然可以pass)! +在Trie search() method 里面,凡是visit过的,mark一下。 + +Regular: +for loop on words: inside, do board DFS based on each word. +Time cpmplexity: word[].length * boardWidth * boardHeight * (4^wordMaxLength) + +Build Trie with target words: insert, search, startWith. +依然要对board matrix做DFS。 + +no for loop on words. 直接对board DFS: +每一层,都会有个up-to-this-point的string. 在Trie里面check它是不是存在。以此判断。 +若不存在,就不必继续DFS下去了。 + +Trie solution time complexity, much better: +build Trie: n * wordMaxLength +search: boardWidth * boardHeight * (4^wordMaxLength + wordMaxLength[Trie Search]) + + +``` /* Given a matrix of lower alphabets and a dictionary. Find all words in the dictionary that can be found in the matrix. A word can start from any position in the matrix and go left/right/up/down to the adjacent position. @@ -40,8 +63,6 @@ */ -//Well, the attempt2 uses Trie, but didn't really use find(). It just uses insert() to create Trie, and mainly -//used the end point where string is finished. /* Attemp2: Trie solution. @@ -66,84 +87,119 @@ In the search: node.subtree.get(current).isString: this determines if a string exists or not. */ + +/*NOTE: is boolean visited on Trie!!! */ public class Solution { - class TrieNode { - boolean isString; - String s; - HashMap subtree; - public TrieNode() { - this.isString = false; - this.s = ""; - this.subtree = new HashMap(); - } - } - - class TrieTree { - TrieNode node; - public TrieTree(TrieNode n) { - node = n; - } - public void insert(String s) { - TrieNode curr = node; - for (int i = 0; i < s.length(); i++) { - if (!curr.subtree.containsKey(s.charAt(i))) { - curr.subtree.put(s.charAt(i), new TrieNode()); - } - curr = curr.subtree.get(s.charAt(i)); - } - curr.isString = true; - curr.s = s; - } - public boolean find(String s) { - TrieNode curr = node; - for (int i = 0; i < s.length(); i++) { - if (!curr.subtree.containsKey(s.charAt(i))) { - return false; - } - curr = curr.subtree.get(s.charAt(i)); - } - return curr.isString; - } - } - - public void search(char[][] board, ArrayList rst, int i, int j, TrieNode node) { - if (node.isString) { - if(!rst.contains(node.s)) { - rst.add(node.s); - } - } - if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] == '#' || node == null) { - return; - } - if (node.subtree.containsKey(board[i][j])) { - char temp = board[i][j]; - TrieNode next = node.subtree.get(board[i][j]); - board[i][j] = '#';//Mark it, prevent going back-forth - search(board, rst, i, j + 1, next); - search(board, rst, i, j - 1, next); - search(board, rst, i - 1, j, next); - search(board, rst, i + 1, j, next); - board[i][j] = temp; - } - - } - public ArrayList wordSearchII(char[][] board, ArrayList words) { - ArrayList rst = new ArrayList(); - if (board == null || words == null || words.size() == 0) { - return rst; - } - TrieTree tree = new TrieTree(new TrieNode()); - for (String word : words) { - tree.insert(word); - } - - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[i].length; j++) { - search(board, rst, i, j, tree.node); - } - } - - return rst; + class TrieNode { + String str; + boolean isEnd; + boolean visited; + HashMap children; + public TrieNode () { + this.isEnd = false; + this.visited = false; + this.str = ""; + children = new HashMap(); + } + } + public TrieNode root; + + public List findWords(char[][] board, String[] words) { + List rst = new ArrayList(); + if (board == null || board.length == 0 || board[0].length == 0 + || words == null || words.length == 0) { + return rst; + } + + //Build Trie with words + root = new TrieNode(); + for (int i = 0; i < words.length; i++) { + insert(words[i]); + } + + //Validate existance of the words in board + boolean[][] visited = new boolean[board.length][board[0].length]; + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + dfs(rst, "", i, j, visited, board); + } + } + + return rst; + } + + //4 direction DFS search + public void dfs(List rst, String s, int x, int y, boolean[][] visited, char[][] board) { + if (x < 0 || x >= board.length || y < 0 || y >= board[0].length) { + return; + } + if (visited[x][y]) { + return; + } + s += board[x][y]; + if (!startWith(s)) { + return; + } + + if (search(s)) { + rst.add(s); + } + int[] dx = {0,0,1,-1}; + int[] dy = {1,-1,0,0}; + visited[x][y] = true; + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + dfs(rst, s, nx, ny, visited, board); + } + visited[x][y] = false; + } + + /**************************Trie section *********************/ + public void insert (String s){ + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + node.children.put(c, new TrieNode()); + } + node = node.children.get(c); + if (i == arr.length - 1) { + node.isEnd = true; + node.str = s; + } + } + } + + public boolean search(String s) { + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + return false; + } + node = node.children.get(c); + } + if (node.visited || !node.isEnd) { + return false; + } + node.visited = true; + return true; + } + + public boolean startWith(String s) { + char[] arr = s.toCharArray(); + TrieNode node = root; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (!node.children.containsKey(c)) { + return false; + } + node = node.children.get(c); + } + return true; } } @@ -151,6 +207,11 @@ public ArrayList wordSearchII(char[][] board, ArrayList words) { + + + + + /* Attempt1: Thoughts: @@ -159,52 +220,61 @@ public ArrayList wordSearchII(char[][] board, ArrayList words) { public class Solution { public ArrayList wordSearchII(char[][] board, ArrayList words) { - ArrayList rst = new ArrayList(); - if (board == null || words == null || words.size() == 0) { - return rst; - } - for (String word : words) { - if (exist(board, word)) { - rst.add(word); - } - } - return rst; + ArrayList rst = new ArrayList(); + if (board == null || words == null || words.size() == 0) { + return rst; + } + for (String word : words) { + if (exist(board, word)) { + rst.add(word); + } + } + return rst; } //The following are from Word Search I public boolean exist(char[][] board, String word) { - if (word == null || word.length() == 0) { - return true; - } - if (board == null) { - return false; - } - - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[0].length; j++) { - if (board[i][j] == word.charAt(0)) { - boolean rst = search(board, word, i, j, 0); - if (rst) { - return true; - } - } - } - } - return false; + if (word == null || word.length() == 0) { + return true; + } + if (board == null) { + return false; + } + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + if (board[i][j] == word.charAt(0)) { + boolean rst = search(board, word, i, j, 0); + if (rst) { + return true; + } + } + } + } + return false; } public boolean search(char[][] board, String word, int i, int j, int start) { - if (start == word.length()) { - return true; - } - if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { - return false; - } - board[i][j] = '#'; - boolean rst = search(board, word, i, j - 1, start + 1) - || search(board, word, i, j + 1, start + 1) - || search(board, word, i + 1, j, start + 1) - || search(board, word, i - 1, j, start + 1); - board[i][j] = word.charAt(start); - return rst; + if (start == word.length()) { + return true; + } + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { + return false; + } + board[i][j] = '#'; + boolean rst = search(board, word, i, j - 1, start + 1) + || search(board, word, i, j + 1, start + 1) + || search(board, word, i + 1, j, start + 1) + || search(board, word, i - 1, j, start + 1); + board[i][j] = word.charAt(start); + return rst; } } + + + + + + + + +``` \ No newline at end of file diff --git a/Java/Word Search.java b/Java/Word Search.java old mode 100644 new mode 100755 index 013dbb9..4db111a --- a/Java/Word Search.java +++ b/Java/Word Search.java @@ -1,9 +1,24 @@ +M + +Backtracking: +比较 Brutle。找到开头的字母,然后投入一个recursive找字母的工程:每到一个字母,朝四个方向走。他们之中,有一个true就可以。 + +Note:每次到一个字母,mark一下'#'. 4个path recurse回来后,mark it back. + +Backtracking方法2: +用一个boolean visited[][] + + + +``` /* Given a 2D board and a word, find if the word exists in the grid. -The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. +The word can be constructed from letters of sequentially adjacent cell, +where "adjacent" cells are those horizontally or vertically neighboring. +The same letter cell may not be used more than once. + -Have you met this question in a real interview? Yes Example Given board = @@ -19,52 +34,115 @@ Tags Expand Backtracking +*/ + +/* Thoughts: 1. find starting index i,j 2. Start divde&&conqure: each iteration. - In each interation: make sure board[i][j] == word.charAt(currentCheckingIndex); If not match, return false and terminate the interation + In each interation: make sure board[i][j] == word.charAt(currentCheckingIndex); If not match, return false and terminate the interation 3. Therefore, if (start) == word.length(), that means all previous-start indexes are matched, so we have a match; return true in this case. Note: if can use boolean || boolean || boolean, use it and save processing power: once one boolean works, it won't process the rest || elements -*/ +*/ public class Solution { public boolean exist(char[][] board, String word) { - if (word == null || word.length() == 0) { - return true; - } - if (board == null) { - return false; - } - - for (int i = 0; i < board.length; i++) { - for (int j = 0; j < board[0].length; j++) { - if (board[i][j] == word.charAt(0)) { - boolean rst = search(board, word, i, j, 0); - if (rst) { - return true; - } - } - } - } - return false; + if (word == null || word.length() == 0) { + return true; + } + if (board == null) { + return false; + } + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + if (board[i][j] == word.charAt(0)) { + boolean rst = search(board, word, i, j, 0); + if (rst) { + return true; + } + } + } + } + return false; } public boolean search(char[][] board, String word, int i, int j, int start) { - if (start == word.length()) { - return true; - } - if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { - return false; - } - board[i][j] = '#'; - boolean rst = search(board, word, i, j - 1, start + 1) - || search(board, word, i, j + 1, start + 1) - || search(board, word, i + 1, j, start + 1) - || search(board, word, i - 1, j, start + 1); - board[i][j] = word.charAt(start); - return rst; + if (start == word.length()) { + return true; + } + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { + return false; + } + board[i][j] = '#'; + boolean rst = search(board, word, i, j - 1, start + 1) + || search(board, word, i, j + 1, start + 1) + || search(board, word, i + 1, j, start + 1) + || search(board, word, i - 1, j, start + 1); + board[i][j] = word.charAt(start); + return rst; + } +} + + + +//dfs: search through the board, going to different directions, while also increasing index. when index == word.length, that's end. +//use visited[][] to mark visited places. + +public class Solution { + public boolean exist(char[][] board, String word) { + if (board == null || board.length == 0 || board[0] == null + || board[0].length == 0 || word == null || word.length() == 0) { + return false; + } + int height = board.length; + int width = board[0].length; + boolean[][] visited = new boolean[height][width]; + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + if (word.charAt(0) != board[i][j]) { + continue; + } + if (dfs(0, i, j, visited, board, word)) { + return true; + } + } + } + return false; + } + + public boolean dfs (int index, int x, int y, boolean[][] visited, char[][] board, String word) { + if (index == word.length()) { + return true; + } + + int height = board.length; + int width = board[0].length; + if (x < 0 || x >= height || y < 0 || y >= width || board[x][y] != word.charAt(index) || visited[x][y]) { + return false; + } + + int[] dx = {1, -1, 0, 0}; + int[] dy = {0, 0, 1, -1}; + visited[x][y] = true; + for (int i = 0; i < 4; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + if (dfs(index + 1, nx, ny, visited, board, word)) { + return true; + } + } + visited[x][y] = false; + return false; } } + + + + + +``` \ No newline at end of file diff --git a/Java/Zigzag Iterator.java b/Java/Zigzag Iterator.java new file mode 100644 index 0000000..e0d02fd --- /dev/null +++ b/Java/Zigzag Iterator.java @@ -0,0 +1,90 @@ +这个题目相对简单. 做的时候我先考虑起来k条怎么办. 那么用个map把index和每个listmark一下就好了。 +每次next(), 相应的list的头拿下来就好。 +然后就跑圈呗,每次刷一个list头。不难。只要把几个variable维护清楚就行。 +``` +/* +Given two 1d vectors, implement an iterator to return their elements alternately. + +For example, given two 1d vectors: + +v1 = [1, 2] +v2 = [3, 4, 5, 6] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1, 3, 2, 4, 5, 6]. + +Follow up: What if you are given k 1d vectors? How well can your code be extended to such cases? + +Clarification for the follow up question - Update (2015-09-18): +The "Zigzag" order is not clearly defined and is ambiguous for k > 2 cases. If "Zigzag" does not look right to you, replace "Zigzag" with "Cyclic". For example, given the following input: + +[1,2,3] +[4,5,6,7] +[8,9] +It should return [1,4,8,2,5,9,3,6,7]. + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Flatten 2D Vector, (M) Peeking Iterator + +*/ + +/* +Thoughts: +HashMap +alter the index to pick correct list +maintain a total size variable. +hashNext: size > 0? +next(): while(map.get(index).length() == 0) : find next list. +return list.get(0), also list.remove(0) + +Note: be careful with all the size, length, index. size does not change once fixed. Remember in next(): index++ and length--; +*/ +public class ZigzagIterator { + private HashMap> map; + private int length = 0; + private int size = 0; + private int index = 0; + public ZigzagIterator(List v1, List v2) { + map = new HashMap>(); + if (v1 != null && v1.size() > 0) { + map.put(size, v1); + length += v1.size(); + size++; + } + if (v2 != null && v2.size() > 0) { + map.put(size, v2); + length += v2.size(); + size++; + } + if (length == 0) { + return; + } + } + + public int next() { + while(map.get(index).size() == 0) { + index++; + if (index == size) { + index = 0; + } + } + int rst = map.get(index).get(0); + map.get(index).remove(0); + length--; + index++; + if (index == size) { + index = 0; + } + return rst; + } + + public boolean hasNext() { + return length > 0; + } +} + + +/** + * Your ZigzagIterator object will be instantiated and called as such: + * ZigzagIterator i = new ZigzagIterator(v1, v2); + * while (i.hasNext()) v[f()] = i.next(); + */ +``` \ No newline at end of file diff --git a/Java/reverseInteger.java b/Java/reverseInteger.java new file mode 100644 index 0000000..22df33d --- /dev/null +++ b/Java/reverseInteger.java @@ -0,0 +1,35 @@ +/* +Reverse Integer + +Reverse digits of an integer. + +Example1: x = 123, return 321 +Example2: x = -123, return -321 +//input = 1534236469 + +Thinking process: +Make sure of operators. +Note: check for overflow using long. When integer is > Integer.MAX_VALUE, then it's overflow. +Initialize long : long x = 1234L; +Convert using (int) + +*/ +public class Solution { + public int reverse(int x) { + if (x == 0) { + return x; //123 + } + boolean sign = x > 0; //sign = true + long rst = 0L; + x = Math.abs(x); // 123 + while (x != 0) { //x = 123, 12, 1 + rst = rst * 10 + x % 10; //rst = 3, 30 + 2 = 32, 320 + 1 = 321 + x = x / 10; //x = 12; 1; 0 + } + if (rst < 0 || rst > Integer.MAX_VALUE) { + return 0; + } + return sign ? (int)rst : -(int)rst; + } +} + diff --git a/Others/CheckClock.java b/Others/CheckClock.java new file mode 100644 index 0000000..cda236b --- /dev/null +++ b/Others/CheckClock.java @@ -0,0 +1,87 @@ +import java.io.*; +import java.util.*; + +/* + R.L. + 12 spots to fill 4P, 4N, 4D. make sure they are not jumping onto each other. + P: move 1 step. + N: 5. + D: 10 + */ + +// +class Solution { + + // Generate all valid 12-length strings + public static void generateAll(ArrayList solutions, String current, int p, int n, int d) { + if (current.length() == 12) { + solutions.add(current); + return; + } + + if (p > 0) generateAll(solutions, current + "P", p - 1, n, d); + if (n > 0) generateAll(solutions, current + "N", p, n - 1, d); + if (d > 0) generateAll(solutions, current + "D", p, n, d - 1); + } + + + // Return true whether the string solution is valid, or false otehrwise + public static boolean isValid(String solution) { + if (solution == null || solution.length() != 12) + return false; + + boolean[] clock = new boolean[12]; + int pointer = 0; + + for (int c = 0; c < 12; c++) { + if (clock[pointer]) + return false; + + int advance = 0; + switch (solution.charAt(c)) { + case 'P': advance = 1; break; + case 'N': advance = 5; break; + case 'D': advance = 10; break; + } + + clock[pointer] = true; + pointer = (pointer + advance) % 12; + } + + for (int c = 0; c < 12; c++) { + if (!clock[c]) + return false; + } + return true; + } + + + // Generate all valid strings, then filter them out and only print the valid ones + public static void printSolution() { + ArrayList solutions = new ArrayList(); + generateAll(solutions, "", 4, 4, 4); + + for (String s : solutions) { + if (isValid(s)) + System.out.println(s); + } + } + + + + public static void main(String[] args) { + printSolution(); + + /* + ArrayList rst = validateClock(); + System.out.println(rst.size()); + for (String string : rst) { + System.out.println(string); + } + */ + } +} + + + +///Generate all possible solutions, then validate them all. \ No newline at end of file diff --git a/Others/HackerrankNote.md b/Others/HackerrankNote.md new file mode 100755 index 0000000..6381dc3 --- /dev/null +++ b/Others/HackerrankNote.md @@ -0,0 +1,9 @@ +Notes: +System ouput: What out for format with space: " " +Don't println() when print() is needed. + Or: can choose to build a String rst, and print at the end. + +Be careful with root node : ) always + +Safe way to do LCA on Binary Search Tree: traditional way of 2 lists + diff --git a/Others/Insert a node into a sorted doubly linked list.java b/Others/Insert a node into a sorted doubly linked list.java new file mode 100755 index 0000000..d8434ce --- /dev/null +++ b/Others/Insert a node into a sorted doubly linked list.java @@ -0,0 +1,70 @@ +E + +Hackerrank. 注意处理null case. 找第一个比curr node 大的 next node. + +``` + +/* +You’re given the pointer to the head node of a sorted doubly linked list and an integer to insert into the list. Create a node and insert it into the appropriate position in the list. The head node might be NULL to indicate that the list is empty. + +Input Format +You have to complete the Node* SortedInsert(Node* head, int data) method which takes two arguments - the head of the sorted, doubly linked list and the value to insert. You should NOT read any input from stdin/console. + +Output Format +Create a node with the given data and insert it into the given list, making sure that the new list is also sorted. Then return the head node of the updated list. Do NOT print anything to stdout/console. + +Sample Input + +NULL , data = 2 +NULL <-- 2 <--> 4 <--> 6 --> NULL , data = 5 + +Sample Output + +NULL <-- 2 --> NULL +NULL <-- 2 <--> 4 <--> 5 <--> 6 --> NULL +Explanation +1. We have an empty list, 2 is inserted. +2. Data 5 is inserted such as list remains sorted. +*/ + +/* + Insert Node at the end of a linked list + head pointer input could be NULL as well for empty list + Node is defined as + class Node { + int data; + Node next; + Node prev; + } +*/ +//If head and tail both null, just insert to head.next +//Else, insert based on data +Node SortedInsert(Node head,int data) { + Node node = new Node(); + node.data = data; + if (head == null && head.next == null) { + node.prev = head; + node.next = head.next; + head.next = node; + return head; + } + + Node fast = head; + while (fast.next != null && node.data > fast.next.data) { + fast = fast.next; + } + if (fast.next == null) { + fast.next = node; + node.prev = fast; + node.next = null; + } else { + Node next = fast.next; + fast.next = node; + node.prev = fast; + node.next = next; + next.prev = node; + } + return head; +} + +``` \ No newline at end of file diff --git a/Others/Matching Same Text Again & Again.java b/Others/Matching Same Text Again & Again.java new file mode 100644 index 0000000..e63f4ce --- /dev/null +++ b/Others/Matching Same Text Again & Again.java @@ -0,0 +1,88 @@ +E + +后面需要重复的pattern,用括号包起来。 + +``` +/* +Hackerrank +https://www.hackerrank.com/contests/regular-expresso/challenges/matching-same-text-again-again +Matching Same Text Again & Again + +\𝗀𝗋𝗈𝗎𝗉_𝗇𝗎𝗆𝖻𝖾𝗋\group_number + +This tool (\1 references the first capturing group) matches the same text as previously matched by the capturing group. + +ach18.png +In the above image, the Regex Pattern is matched with the Test String. +In the above image, the Regex Pattern is matched with the Test String. + +For Example: + +(\d)\1: It can match 00, 11, 22, 33, 44, 55, 66, 77, 88 or 99. + +Task + +You have a test string SS. +Your task is to write a regex that will match SS with the following conditions: + +SS must be of length: 20 +1st1st character: lowercase letter. +2nd2nd character: word character. +3rd3rd character: whitespace character. +4th4th character: non word character. +5th5th character: digit. +6th6th character: non digit. +7th7th character: uppercase letter. +8th8th character: letter (either lowercase or uppercase). +9th9th character: vowel (a, e, i , o , u, A, E, I, O or U). +10th10th character: non whitespace character. +11th11th character: should be same as 1st character. +12th12th character: should be same as 2nd character. +13th13th character: should be same as 3rd character. +14th14th character: should be same as 4th character. +15th15th character: should be same as 5th character. +16th16th character: should be same as 6th character. +17th17th character: should be same as 7th character. +18th18th character: should be same as 8th character. +19th19th character: should be same as 9th character. +20th20th character: should be same as 10th character. +Note + +This is a regex only challenge. You are not required to write code. +You have to fill the regex pattern in the blank (_________). + +*/ + +import java.io.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.util.regex.*; + + +public class Solution { + + public class Solution { + + public static void main(String[] args) { + + Regex_Test tester = new Regex_Test(); + tester.checker("([a-z])(\\w)(\\s)(\\W)(\\d)(\\D)([A-Z])([a-zA-Z])([a|e|i|o|u|A|E|I|O|U])(\\S)\\1\\2\\3\\4\\5\\6\\7\\8\\9\\10"); // Use \\ instead of using \ + + } + } +} + +class Regex_Test { + + public void checker(String Regex_Pattern){ + + Scanner Input = new Scanner(System.in); + String Test_String = Input.nextLine(); + Pattern p = Pattern.compile(Regex_Pattern); + Matcher m = p.matcher(Test_String); + System.out.println(m.find()); + } + +} +``` \ No newline at end of file diff --git a/Others/MorseCode.java b/Others/MorseCode.java new file mode 100644 index 0000000..00b2649 --- /dev/null +++ b/Others/MorseCode.java @@ -0,0 +1,122 @@ +想法: +1. 只关注正数,找一个分割点,开始查看能不能有valid的解。 +2. 过程中,把正数可能有的所有正数的解都找出来,可能存为一个ArrayList letters in morse format: +String 是 "... --- ..." 每个字母之间有空格分开。 +这里可能生成所有possibilities。 其中有很多possibility在结合了负数后,可能就会不成立。 + +3. loop through arraylist: letters +根据每个字母,以及每个字母后面的停顿,来尝试跟所有的负数,分段比较。 +比如第一个字母:[. -x . -y . -z] z 肯定比x 和y都大; 而SOS后面的空出来的负数时间,应该比这个词里面的所有负数绝对值都大。 + +这样就把ArrayList Letters 里面的很多可能性都灭掉。出一个或者多个结果~ + + + +当然:这里负数只做了最终判断的作用,而一开始正数出的结果可能会非常耗时。 +而且假设了分段判断的规律,而不假设全局的规律。(好像更切合实际)。 + + +``` +//Trie + + +import java.io.*; +import java.util.*; + +/* + * To execute Java, please define "static void main" on a class + * named Solution. + * + * If you need more classes, simply define them inline. + */ + + +/* +Double[] = {0.15, -0.12, 0.16, -0.1, 0.17, -0.3} +pos: . - time +neg: empty time + + morseCodeDict["A"] = ".-" + morseCodeDict["B"] = "-..." + morseCodeDict["C"] = "-.-." + morseCodeDict["D"] = "-.." + morseCodeDict["E"] = "." + morseCodeDict["F"] = "..-." + morseCodeDict["G"] = "--." + morseCodeDict["H"] = "...." + morseCodeDict["I"] = ".." + morseCodeDict["J"] = ".---" + morseCodeDict["K"] = "-.-" + morseCodeDict["L"] = ".-.." + morseCodeDict["M"] = "--" + morseCodeDict["N"] = "-." + morseCodeDict["O"] = "---" + morseCodeDict["P"] = ".--." + morseCodeDict["Q"] = "--.-" + morseCodeDict["R"] = ".-." + morseCodeDict["S"] = "..." + morseCodeDict["T"] = "-" + morseCodeDict["U"] = "..-" + morseCodeDict["V"] = "...-" + morseCodeDict["W"] = ".--" + morseCodeDict["X"] = "-..-" + morseCodeDict["Y"] = "-.--" + morseCodeDict["Z"] = "--.." + + morseCodeDict["1"] = "-----" + morseCodeDict["2"] = ".----" + morseCodeDict["3"] = "..---" + morseCodeDict["4"] = "...--" + morseCodeDict["5"] = "....-" + morseCodeDict["6"] = "....." + morseCodeDict["7"] = "-...." + morseCodeDict["8"] = "--..." + morseCodeDict["9"] = "---.." + morseCodeDict["0"] = "----." + +Example: +[0.0450931929901705, -0.0901581814005595, 0.0678896922281069, -0.121032138856854, 0.152995205350165, -0.276777733213167, 0.275236261113044, -0.0919186682910514, 0.347645293572589, -0.125459771265131, 0.342321600880377, -0.363701690087054, 0.102393076997638, -0.117040938252157, 0.114223775510942, -0.0895479217582997, 0.0973858877985071] = SOS ...---... + +Thoughts: +Pos: +Two sets: dot or dash. +Negative: +Three sets: time between morse code, time between letter, time between words. + +Pick a pos time for '.', pick a negtive time for time between morse code, then start DFS. + +For initial judgement: +Pos: +Sort all postive number, let the smallest be '.' and the rest to be '-'. try it out. If not working, move the threshold. + +Negative: +Sort by absolute value. +Assume all letters are the shortest one morse code. So the set for 'time between word' will have most of number. + The set for 'time between letter' will be empty + The set for 'time between morse code' will be empty +If not working, move number around the tree sets, and do dfs. + +The possible solution is to try all posibility with dfs, and cut it off when it seems not valid. + + + +Thought2: +Ignore negative for now. Try to use same method for positive number to try out all posibilities with postiive numbers. +Use the results to match negative numbers, see if the time pulse is valid. +If match, return all posibilities. + +*/ +class Solution { + public static void main(String[] args) { + ArrayList strings = new ArrayList(); + strings.add("Hello, World!"); + strings.add("Welcome to CoderPad."); + strings.add("This pad is running Java 8."); + + for (String string : strings) { + System.out.println(string); + } + } +} + +``` \ No newline at end of file diff --git a/Others/README.md b/Others/README.md new file mode 100755 index 0000000..43da067 --- /dev/null +++ b/Others/README.md @@ -0,0 +1,5 @@ +# Other Problems + +This section captures other programs that does not appear in LintCode. There might not be a clear solution to problems here, but here we'll try to capture some 'how to' or good thoughts. + +And, due to the non-consistency, there won't be auto-generated list view : ). \ No newline at end of file diff --git a/Others/RemoveNodeFromLinkedList.java b/Others/RemoveNodeFromLinkedList.java new file mode 100644 index 0000000..ebd0c86 --- /dev/null +++ b/Others/RemoveNodeFromLinkedList.java @@ -0,0 +1,22 @@ +//Remove node from linkedlist + //H L L L 0 + Node current = head;//L + Node node = current; + Node prev = new Node('0'); + prev.next = node; + while (current != null) {//1L + + while (node.next != null) {//21L + if (current.value == node.next.value ) { + prev.next = prev.next.next; + } + prev = prev.next; + node = node.next; + + } + prev = current; + current = current.next; + node = current; + } + return head; + \ No newline at end of file diff --git a/Others/Solution$TreeNode.class b/Others/Solution$TreeNode.class new file mode 100644 index 0000000..d9e0891 Binary files /dev/null and b/Others/Solution$TreeNode.class differ diff --git a/Others/Solution.class b/Others/Solution.class new file mode 100644 index 0000000..7aa4049 Binary files /dev/null and b/Others/Solution.class differ diff --git a/Others/Solution.java b/Others/Solution.java new file mode 100644 index 0000000..5d5224b --- /dev/null +++ b/Others/Solution.java @@ -0,0 +1,124 @@ +import java.io.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.util.regex.*; +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + //BFS. store as string, separated by ',' +class Solution { + class TreeNode { + public int val; + public TreeNode left, right; + public TreeNode(int val) { + this.val = val; + this.left = this.right = null; + } + } + + /** + * This method will be invoked first, you should design your own algorithm + * to serialize a binary tree which denote by a root node to a string which + * can be easily deserialized by your own "deserialize" method later. + */ + public String serialize(TreeNode root) { + String rst = ""; + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + queue.offer(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode node = queue.poll(); + rst += node.val + ","; + if (node.left == null) { + rst += "#,"; + } else { + queue.offer(node.left); + } + if (node.right == null) { + rst += "#,"; + } else { + queue.offer(node.right); + } + + } + }//end while + System.out.println("here rst: " + rst); + return rst; + } + + /** + * This method will be invoked second, the argument data is what exactly + * you serialized at method "serialize", that means the data is not given by + * system, it's given by your own serialize method. So the format of data is + * designed by yourself, and deserialize it here as you serialize it in + * "serialize" method. + */ + public TreeNode deserialize(String data) { + if (data == null) { + return null; + } + TreeNode root = new TreeNode(0); + root.val = Integer.parseInt(data.substring(0, data.indexOf(","))); + data = data.substring(data.indexOf(",") + 1); + + Queue queue = new LinkedList(); + queue.offer(root); + int size = 0; + while (!queue.isEmpty()) { + size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode node = queue.poll(); + String temp = data.substring(0, data.indexOf(",")); + if (!temp.equals("#")) { + node.left = new TreeNode(Integer.parseInt(temp)); + } + data = data.substring(data.indexOf(",") + 1); + + temp = data.substring(0, data.indexOf(",")); + if (!temp.equals("#")) { + node.right = new TreeNode(Integer.parseInt(temp)); + } + data = data.substring(data.indexOf(",") + 1); + } + } + + return root; + } + + public TreeNode init() { + TreeNode head = new TreeNode(1); + head.left = new TreeNode(2); + head.right = new TreeNode(3); + return head; + } + public static void main(String[] args) { + System.out.println("test"); + Solution test = new Solution(); + + + + String str = test.serialize(test.init()); + System.out.println(); + } + +} + + + + + diff --git a/Others/Sort Anagram.java b/Others/Sort Anagram.java new file mode 100755 index 0000000..2679a35 --- /dev/null +++ b/Others/Sort Anagram.java @@ -0,0 +1,12 @@ +/* + Sort Anagram + My guess this problem is: Sort a list of strings and make sure all the anagrams are grouped together. + + The clarification needed would be: + 1. Does the output need to be in alphabetical order and how to define the rules, since anagram will not be in perfect order comparing with other non-same-group strings. + + 2. If no need of alphabetical order, but just group anagram words together, this would turn to a regular anagram problem. + Use HashMap to store sorted string as KEY, and a list of strings as value. + Then output all contents from map. + +*/ \ No newline at end of file diff --git a/Others/TopTenURL.java b/Others/TopTenURL.java new file mode 100755 index 0000000..af56bfd --- /dev/null +++ b/Others/TopTenURL.java @@ -0,0 +1,35 @@ +/* + Given a list of URLs, find top 10 most visited URLs + + Some points this problem might cover: + + +*/ + +/* + 1. MapReduce related problem + http://stackoverflow.com/questions/17928158/find-top-10-most-frequent-visited-url-data-is-stored-accross-network# + To mimic the process of MapReduce. + + One most voted solution: + It says you can't use map-reduce directly which is a hint the author of the question wants you to think how map reduce works, so we will just mimic the actions of map-reduce: + + pre-processing: let R be the number of servers in cluster, give each server unique id from 0,1,2,...,R-1 + (map) For each (string,id) - send the tuple to the server which has the id hash(string) % R. + (reduce) Once step 2 is done (simple control communication), produce the (string,count) of the top 10 strings per server. Note that the tuples where those sent in step2 to this particular server. + (map) Each server will send all his top 10 to 1 server (let it be server 0). It should be fine, there are only 10*R of those records. + (reduce) Server 0 will yield the top 10 across the network. + + Notes: + + The problem with the algorithm, like most big-data algorithms that don't use frameworks is handling failing servers. MapReduce takes care of it for you. + The above algorithm can be translated to a 2 phases map-reduce algorithm pretty straight forward. +*/ + + +/* + 2. Top K words in a document: + This is an actaul problem on LintCode + http://www.zrzahid.com/top-k-or-k-most-frequent-words-in-a-document/ + http://www.geeksforgeeks.org/find-the-k-most-frequent-words-from-a-file/ +*/ \ No newline at end of file diff --git a/Others/Tree-Huffman Decoding.java b/Others/Tree-Huffman Decoding.java new file mode 100755 index 0000000..91b33a9 --- /dev/null +++ b/Others/Tree-Huffman Decoding.java @@ -0,0 +1,129 @@ +M + +读.很长的题目。最后不过是:根据input char array, 找到leaf, print罢了。 + +这里frequency没有用到。可能构建这个Huffman Tree会更难 + +``` + + +/* +Huffman coding assigns variable length codewords to fixed length input characters based on their frequencies. More frequent characters are assigned shorter codewords and less frequent characters are assigned longer codewords. A huffman tree is made for the input string and characters are decoded based on their position in the tree. We add a '0' to the codeword when we move left in the binary tree and a '1' when we move right in the binary tree. We assign codes to the leaf nodes which represent the input characters. + +For example : + + {ϕ,5} + 0 / \ 1 + {ϕ,2} {A,3} + 0/ \1 +{B,1} {C,1} +Input characters are only present on the leaves. Internal nodes have a character value of ϕ. Codewords: + +A - 1 +B - 00 +C - 01 +No codeword appears as a prefix of any other codeword. Huffman encoding is a prefix free encoding technique. + +Encoded String "1001011" represents the string "ABACA" + +You have to decode an encoded string using the huffman tree. + +You are given pointer to the root of the huffman tree and a binary coded string. You need to print the actual string. + +Input Format + +You are given a function, + +void decode_huff(node * root, string s) +{ + +} +The structure for node is defined as : + +struct node +{ + int freq; + char data; + node * left; + node * right; + +}node; +Note: +Internal nodes have data='\0'(ϕ ) + +Output Format + +Output the decoded string on a single line. + +Sample Input + + {ϕ,5} + 0 / \ 1 + {ϕ,2} {A,3} + 0/ \1 +{B,1} {C,1} + +S="1001011" +Sample Output + +ABACA +Explanation + +S="1001011" +Processing the string from left to right. +S[0]='1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string. +We move back to the root. + +S[1]='0' : we move to the left child. +S[2]='0' : we move to the left child. We encounter a leaf node with value 'B'. We add 'B' to the decoded string. +We move back to the root. + +S[3] = '1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string. +We move back to the root. + +S[4]='0' : we move to the left child. +S[5]='1' : we move to the right child. We encounter a leaf node with value C'. We add 'C' to the decoded string. +We move back to the root. + + S[6] = '1' : we move to the right child of the root. We encounter a leaf node with value 'A'. We add 'A' to the decoded string. +We move back to the root. + +Decoded String = "ABACA" + +*/ + +/* + class Node + public int frequency; // the frequency of this tree + public char data; + public Node left, right; + +*/ +//Based on the input S.toCharArray(), and use the char to find leaf. Print leaf +void decode(String S ,Node root) { + if (root == null) { + return; + } + char[] arr = S.toCharArray(); + int index = 0; + String rst = ""; + while (index < arr.length) { + Node node = root; + while (node != null) { + if (node.left == null && node.right == null) { + rst += node.data; + break;//break inner while + } else { + char c = arr[index]; + if (c == '0') { + node = node.left; + } else { + node = node.right; + } + index++; + } + } + } + System.out.println(rst); +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/GenerateCodeTable.class b/Others/old records/LeetCode-Merged/GenerateCodeTable.class new file mode 100644 index 0000000..598affa Binary files /dev/null and b/Others/old records/LeetCode-Merged/GenerateCodeTable.class differ diff --git a/Others/old records/LeetCode-Merged/GenerateCodeTable.java b/Others/old records/LeetCode-Merged/GenerateCodeTable.java new file mode 100644 index 0000000..8da91b3 --- /dev/null +++ b/Others/old records/LeetCode-Merged/GenerateCodeTable.java @@ -0,0 +1,123 @@ +import java.io.*; +/* +Used to generate table of contents. +1. No args: generate both tables +2. args == 'word', generate WordPress table. +3. args == 'git', genereate GitHub table. +*/ +public class GenerateCodeTable { + public static void main(String[] args) { + //Read Java Solution Folder + File folder = new File("./Java");//"." = current path + if (!folder.exists() || !folder.isDirectory()) { + System.out.println("Check Directory:1"); + return; + } + File[] listOfFiles = folder.listFiles(); + if (listOfFiles == null) { + System.out.println("Check Directory:2"); + return; + } + + String outputContent = ""; + File outFile; + + if (args.length == 0){ + outputContent = generateREADME(listOfFiles); + printPage("README.md", outputContent); + outputContent = generateWordPressPage(listOfFiles); + printPage("WordPress.txt", outputContent); + } else if (args != null && args[0].contains("word")) {//Wordpress + outputContent = generateWordPressPage(listOfFiles); + printPage("WordPress.txt", outputContent); + } else if (args != null && args[0].contains("git")) { + outputContent = generateREADME(listOfFiles); + printPage("README.md", outputContent); + } else { + return; + } + + + } + /* + Generate Wordpress Table + */ + public static String generateWordPressPage(File[] listOfFiles) { + //Assemble output + String outputContent = "Java Solutions to problems from LeetCode(https://leetcode.com/problemset/algorithms/).\n" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + int count = 0; + for (File file : listOfFiles) { + if (file.getName().contains(".java")) { + //outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/awangdev/LintCode/blob/master/Java/"+ file.getName() +")| |" + "Java|\n"; + outputContent+= + "" + + "" + + "" + + "" + + "" + + ""; + count++; + } + } + + outputContent += "
#Problem      Level  Language
" + count + "" + file.getName() + "Java
"; + return outputContent; + } + + + /* + Generate GitHub ReadMe file + */ + public static String generateREADME(File[] listOfFiles) { + //Assemble output + String outputContent = "# LeetCode\n\n" + + "To host Java Solutions to problems from LeetCode(https://leetcode.com/problemset/algorithms/).\n" + + "I Will try to revise the solutions once new problem or new testing case occurs.\n" + + "Since I do not run .java files, they are formatted with markdowns to help compressing code in blog format.\n\n"+ + "| Squence | Problem | Level | Language |\n" + + "|:-------:|:--------------|:---------------|:---------:|\n"; + int count = 0; + for (File file : listOfFiles) { + if (file.getName().contains(".java")) { + outputContent += "|" + count + "|[" + file.getName() + "](https://github.com/awangdev/LeetCode/blob/master/Java/"+ file.getName() +")| |" + "Java|\n"; + count++; + } + } + return outputContent; + } + /* + Generate a combined post of all files, with proper markdown + */ + public static String generateCombinedPost() { + return ""; + } + /* + Write the outputContent to specific file + */ + public static void printPage(String fileName, String outputContent) { + System.out.println(outputContent); + try { + File outFile = new File(fileName); + FileOutputStream fop = new FileOutputStream(outFile); + byte[] contentInBytes = outputContent.getBytes(); + fop.write(contentInBytes); + fop.flush(); + fop.close(); + System.out.println("Mission Accomplished. Now go ahead and commit"); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/3Sum Smaller.java b/Others/old records/LeetCode-Merged/Java/3Sum Smaller.java new file mode 100644 index 0000000..55642b1 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/3Sum Smaller.java @@ -0,0 +1,58 @@ +一般的O(n3)肯定不行。在此基础上优化。 +发现j,k满足条件时候,(k - j)就是所有 sum target, 又因为j不能后退,只能k--,那么问题就被锁定了. 这样可以做到O(n2) +``` +/* +Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target. + +For example, given nums = [-2, 0, 1, 3], and target = 2. + +Return 2. Because there are two triplets which sums are less than 2: + +[-2, 0, 1] +[-2, 0, 3] + +Follow up: +Could you solve it in O(n2) runtime? + +Tags: Array Two Pointers +Similar Problems:(M) 3Sum, (M) 3Sum Closest + +*/ + + +/* +Thoughts: +Similar to 3 sum, but ofcourse, this one check on '<' so we can not use HashMap anymore. +Basic concept is to fix first number, then check for the rest two numbers, see if they addup < target. +When checking j and k, realize something nice: + if nums[j] + nums[k] < target - nums[i], that means for all index <= k will work, so directly add (k - j) to result (that's: index = j+1, j+2, ....,k) + also, move j forward for next round. +OR, if three-add-up >= target, since j can only increase, we do k-- to make the three-add-up smaller + +Note: +Don't forget to sort, otherwise the sequence/order is unpredictable +*/ +public class Solution { + public int threeSumSmaller(int[] nums, int target) { + if (nums == null || nums.length <= 2) { + return 0; + } + Arrays.sort(nums); + int rst = 0; + for (int i = 0; i < nums.length - 2; i++) { + int j = i + 1; + int k = nums.length - 1; + while (j < k) { + if (nums[i] + nums[j] + nums[k] >= target) { + k--; + } else { + rst += (k - j); + j++; + } + } + }//END for + return rst; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/3Sum.java b/Others/old records/LeetCode-Merged/Java/3Sum.java new file mode 100644 index 0000000..6d77930 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/3Sum.java @@ -0,0 +1,78 @@ +/* +Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? +Find all unique triplets in the array which gives the sum of zero. + +Note: +Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c) +The solution set must not contain duplicate triplets. + For example, given array S = {-1 0 1 2 -1 -4}, + + A solution set is: + (-1, 0, 1) + (-1, -1, 2) +Hide Company Tags Facebook +Hide Tags Array Two Pointers +Hide Similar Problems (M) Two Sum (M) 3Sum Closest (M) 4Sum (M) 3Sum Smaller + +*/ +/* + Thoughts: + sort list. O(nLogn) + end: n^2 + for (i = 0 ~ n) { + int target = 0 - nums[i]; + while (start + 1 < end) { + start + end == target { + rst.add(i, star, end); + keep looking: start ++, end-- + } + else start + end < target? + start++ + else + end--; + } + } + } + +Note: + Check duplicates. Compute a unique string to savei set +*/ + +public class Solution { + public List> threeSum(int[] nums) { + List> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + + Arrays.sort(nums); + HashSet set = new HashSet(); + //use old target to check duplicates. instead of set. + for (int i = 0; i < nums.length - 2; i++) { + int target = 0 - nums[i]; + int start = i + 1; + int end = nums.length - 1; + + ArrayList list = new ArrayList(); + while (start < end) { + if (nums[start] + nums[end] == target && + !set.contains(nums[i] + "," + nums[start] + "," + nums[end])) { + list.add(nums[i]); + list.add(nums[start]); + list.add(nums[end]); + rst.add(list); + set.add(nums[i] + "," + nums[start] + "," + nums[end]); + list = new ArrayList(); + start++; + end--; + } else if (nums[start] + nums[end] < target) { + start++; + } else { + end--; + } + }//end while + } + + return rst; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Alien Dictionary.java b/Others/old records/LeetCode-Merged/Java/Alien Dictionary.java new file mode 100644 index 0000000..da58127 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Alien Dictionary.java @@ -0,0 +1,56 @@ +/* +There is a new alien language which uses the latin alphabet. +However, the order among letters are unknown to you. +You receive a list of words from the dictionary, where words are sorted lexicographically by the rules of this new language. +Derive the order of letters in this language. + +For example, +Given the following words in dictionary, + +[ + "wrt", + "wrf", + "er", + "ett", + "rftt" +] +The correct order is: "wertf". + +Note: +You may assume all letters are in lowercase. +If the order is invalid, return an empty string. +There may be multiple valid order of letters, return any one of them is fine. +Hide Company Tags Google Facebook +Hide Tags Graph Topological Sort +Hide Similar Problems (M) Course Schedule II + +*/ + +/* + NOT DONE + Thoughts: + They have sink node. They form a valid tree, without sycle. + A char can visit another node, does not mean they have order. + A char appear in a lower row means they have different order. + For 1st column, w appears before e, e appears before r. + For 2nd column:r appears before t, t appears before f + For 3rd col: t appears before f. + For 4th col, nothing to compare. + So make in[][]: [w,e] [e,r][r,t][t,f] based on the possible order. + + Then do topological sort on the sequence and mark the sequence like in course schedule II +*/ + +public class Solution { + public String alienOrder(String[] words) { + + } +} + + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Binary Search Tree Iterator.java b/Others/old records/LeetCode-Merged/Java/Binary Search Tree Iterator.java new file mode 100644 index 0000000..56f3585 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Search Tree Iterator.java @@ -0,0 +1,86 @@ +李特这的这个题目不错。写一遍example就能看出来inorder traversal。当然啦,不能直接全部traverse了,因为题目说有空间限制。 + +那么就traversal on the fly, 先左手DFS, 然后每次加上一个右手node,都再来一遍左手DFS。 + +存到一个后进先出的数据结构里,stack呗,然后头顶就是最小的了。 + +``` +/* +Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. + +Calling next() will return the next smallest number in the BST. + +Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree. + +Tags: Tree Stack Design +Similar Problems: (M) Binary Tree Inorder Traversal, (M) Flatten 2D Vector, (M) Zigzag Iterator, (M) Peeking Iterator, (M) Inorder Successor in BST + +*/ + +/* +Attempt, Thoughts: +Test + 5 + 3 9 + 1 4 6 10 +return: 1,3,4,5,6,9,10. Looks like in-order taversal style, though don't traversal all at once because we can only store O(h) elements. +However, we can do inorder traversal on the fly, by mantaining a stack. +How about Priority queue of all left-most elements. + Do a run-through on left elements, add them all. + When pop one element: + (it cannot have left, because we've initially added them already) + if has right: + add right node + check right's node's left-most(DFS), added all left nodes and left nodes' left-child +Well.. the way I did it, does not need priority queue. Just use a stack will be fine. +*/ +/** + * Definition for binary tree + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + +public class BSTIterator { + private Stack stack = new Stack(); + public BSTIterator(TreeNode root) { + if (root == null) { + return; + } + stack.push(root); + while(root.left != null) { + root = root.left; + stack.push(root); + } + } + + /** @return whether we have a next smallest number */ + public boolean hasNext() { + return !stack.isEmpty(); + } + + /** @return the next smallest number */ + public int next() { + TreeNode node = stack.pop(); + int rst = node.val; + if (node.right != null) { + node = node.right; + stack.push(node); + while(node.left != null) { + node = node.left; + stack.push(node); + } + } + return rst; + } +} + +/** + * Your BSTIterator will be called like this: + * BSTIterator i = new BSTIterator(root); + * while (i.hasNext()) v[f()] = i.next(); + */ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Binary Tree Inorder Traversal.java b/Others/old records/LeetCode-Merged/Java/Binary Tree Inorder Traversal.java new file mode 100644 index 0000000..9edeb06 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Tree Inorder Traversal.java @@ -0,0 +1,81 @@ +/* +Given a binary tree, return the inorder traversal of its nodes' values. + +For example: +Given binary tree {1,#,2,3}, + 1 + \ + 2 + / + 3 +return [1,3,2]. + +Note: Recursive solution is trivial, could you do it iteratively? + +confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. + + +OJ's Binary Tree Serialization: +The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below. + +Here's an example: + 1 + / \ + 2 3 + / + 4 + \ + 5 +The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}". +*/ + +/* +Thoughts: Need to it iteratively +Steps: +1. added root + all left most (whichever added last, process that first, so STACK) +2. Process the stack, for each node, if right !=null, then add right, called it rightNode +3. Add all rightNode's left child and grandchild ... etc. +Test + 5 + 3 9 + 1 4 6 10 +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public List inorderTraversal(TreeNode root) { + List rst = new ArrayList(); + Stack stack = new Stack(); + if (root == null) { + return rst; + } + //Add left children + dfsOnLeft(stack, root); + //Process + while(!stack.isEmpty()) { + TreeNode node = stack.pop(); + rst.add(node.val); + if (node.right != null) { + node = node.right; + dfsOnLeft(stack, node); + } + }//end while + return rst; + } + + public void dfsOnLeft(Stack stack, TreeNode node) { + stack.push(node); + while(node.left != null) { + node = node.left; + stack.push(node); + } + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Binary Tree Level Order Traversal.java b/Others/old records/LeetCode-Merged/Java/Binary Tree Level Order Traversal.java new file mode 100644 index 0000000..0ad0278 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Tree Level Order Traversal.java @@ -0,0 +1,80 @@ +普通的BFS. +唯一小心就是:每次要把每一Level 的放在一个list里面。也就是说,一旦queue里有东西,那一定就全部是这一个level的。先把size固定一下,把queue里面的东西全部加到这个level的list里面(同时还要继续添加element 进 queue)。没跑完一圈i ~ size, 然后就add那个level list。 +``` +/* +Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). + +For example: +Given binary tree {3,9,20,#,#,15,7}, + 3 + / \\ + 9 20 + / \\ + 15 7 +return its level order traversal as: +[ + [3], + [9,20], + [15,7] +] +confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. + +Tags: Tree Breadth-first Search +Similar Problems: (M) Binary Tree Zigzag Level Order Traversal, (E) Binary Tree Level Order Traversal II, (E) Minimum Depth of Binary Tree + +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +/* +Thoughts: +Looks like BFS. put root in a queue, then put left, right in the queue. +Process the queue until it runs out. + +Note: +Queue: offer() + + +*/ +public class Solution { + public List> levelOrder(TreeNode root) { + List> rst = new ArrayList>(); + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + queue.offer(root); + + while (!queue.isEmpty()) { + int size = queue.size();//Becareful with fixed size + List list = new ArrayList(); + for (int i = 0; i < size; i++) { + TreeNode node = queue.poll(); + list.add(node.val); + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } + rst.add(list); + } + return rst; + } +} + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Binary Tree Longest Consecutive Sequence.java b/Others/old records/LeetCode-Merged/Java/Binary Tree Longest Consecutive Sequence.java new file mode 100644 index 0000000..05d54db --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Tree Longest Consecutive Sequence.java @@ -0,0 +1,125 @@ +屌炸天的4行代码。 +我洋洋洒洒那么多行,最后还不work.看了solution, 如此精简。 + +主要想法: +Recursive用好。首先在这个level比一比,可否成。 +不成的话,另立门户。 +然后左右开弓。再把结果拿过来比较一下就好了。简单明了。 +``` +/* +Given a binary tree, find the length of the longest consecutive sequence path. + +The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to be from parent to child (cannot be the reverse). + +For example, + 1 + \\ + 3 + / \\ + 2 4 + \\ + 5 +Longest consecutive sequence path is 3-4-5, so return 3. + 2 + \\ + 3 + / + 2 + / + 1 +Longest consecutive sequence path is 2-3,not3-2-1, so return 2. + +Tags:Tree +Similar Problems: (H) Longest Consecutive Sequence + +*/ + +/* +Attemp2: http://www.cnblogs.com/jcliBlogger/p/4923745.html. +The original solution has just 4 lines of C++ code. That hurts. +The concept is very much similar as my attempt1, though the code is more clear with recursive call +1. pass alone a depth. +2. if consecutive, depth++; else, start from depth 1 +3. Go deeper on both left, and right; both with new depth: currDepth; +4. Compare the Max of currDept, left's return, right's return. +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public int longestConsecutive(TreeNode root) { + return recursiveHelper(root, null, 0); + } + + public int recursiveHelper(TreeNode curr, TreeNode parent, int depth) { + if (curr == null) { + return 0; + } + int currDepth = 0; + if (parent != null && parent.val + 1 == curr.val) { + currDepth = depth + 1; + } else { + currDepth = 1; + } + return Math.max(currDepth, Math.max(recursiveHelper(curr.left, curr, currDepth), recursiveHelper(curr.right, curr, currDepth))); + } +} + + +/* +Attemp1, failed. +Thoughts: +Seems like backtracking: we find the lowest level, then return depth, and add it on parent's record if consectutive. +always record a max value. +If node.left != null || node.right != null, if consecutive, node.depth = node.child.depth +1 +If node.left == null && node.right == null, return 1; + + +public class Solution { + private int max = Integer.MIN_VALUE; + public int longestConsecutive(TreeNode root) { + dfsOnNode(root); + return max; + } + + public int dfsOnNode(TreeNode root) { + int depth = 0; + int localMax = Integer.MIN_VALUE; + if (root == null) { + return depth; + } + if (root.left == null && root.right == null) {//ON:right4, + depth++; + return depth; + } + if (root.right != null) {//root.right = 3, right4, + int childDepth = longestConsecutive(root.right);//ON: 3, right4 + if (root.val + 1 == root.right.val) {//3+1=4 + depth = childDepth + 1;//1+1=2 + } else { + depth = 1; + } + } + localMax = Math.max(localMax, depth); + if (root.left != null) { + int childDepth = longestConsecutive(root.left); + if (root.val + 1 == root.left.val) { + depth = childDepth + 1; + } else { + depth = 1; + } + } + localMax = Math.max(localMax, depth); + max = Math.max(max, localMax); + return localMax; + } +} +*/ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Binary Tree Paths.java b/Others/old records/LeetCode-Merged/Java/Binary Tree Paths.java new file mode 100644 index 0000000..bc99f12 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Tree Paths.java @@ -0,0 +1,71 @@ +一幕了然. DFS把tree给过了. +用ArrayList存item比较方便,记得每次backtrack的时候把末尾的item去掉 +``` +list.remove(list.size() - 1); +``` + +``` +/* +Given a binary tree, return all root-to-leaf paths. + +For example, given the following binary tree: + + 1 + / \\ +2 3 + \\ + 5 +All root-to-leaf paths are: + +["1->2->5", "1->3"] +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public List binaryTreePaths(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + ArrayList list = new ArrayList(); + DFS(root, list, rst); + return rst; + } + public void DFS(TreeNode node, ArrayList list, List rst) { + list.add(node.val+""); + if(node.left == null && node.right == null) { + String str = ""; + for (String s : list) { + str += s + "->"; + } + rst.add(str.substring(0, str.length() - 2)); + return; + } + if (node.left != null) { + DFS(node.left, list, rst); + list.remove(list.size() - 1); + } + if (node.right != null) { + DFS(node.right, list, rst); + list.remove(list.size() - 1); + } + } +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Binary Tree Right Side View.java b/Others/old records/LeetCode-Merged/Java/Binary Tree Right Side View.java new file mode 100644 index 0000000..5c7e923 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Binary Tree Right Side View.java @@ -0,0 +1,86 @@ +自己想了这个方法,有可能不是特别efficient. +一个queue放普通的BFS。 +一个queue放level。 +同时维护一个parent value;维护一个跟着BFS跑的level。 +每个node都有一个lv。一旦lv和正在跑的level不一样,证明lv>level,那么也就是说,刚刚换行拉。parent的值,就是上一行最右边的值。DONE. +``` +/* +Given a binary tree, imagine yourself standing on the right side of it, +return the values of the nodes you can see ordered from top to bottom. + +For example: +Given the following binary tree, + 1 <--- + / \\ +2 3 <--- + \\ \\ + 5 4 <--- +You should return [1, 3, 4]. + +Tags: Tree, Depth-first Search, Breadth-first Search +Similar Problems: (M) Populating Next Right Pointers in Each Node + +*/ + +/* +Thoughts: +Use 2 queue: one for BFS, one for level. Each node in queue has a corresponding level +Track level. +WHen level != levelQ.poll(), that means we are moving to next level, and we should record the previous(parent) node's value. +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public List rightSideView(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + Queue q = new LinkedList(); + Queue levelQ = new LinkedList(); + q.offer(root); + levelQ.offer(1); + int level = 1; + int parent = root.val; + TreeNode node = null; + + while (!q.isEmpty()) { + node = q.poll(); + int lv = levelQ.poll(); + if (level != lv) { + level++; + rst.add(parent); + } + parent = node.val; + if (node.left != null) { + q.offer(node.left); + levelQ.offer(lv + 1); + } + if (node.right != null) { + q.offer(node.right); + levelQ.offer(lv + 1); + } + }//END while + rst.add(parent); + return rst; + } +} + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Building Outline.java b/Others/old records/LeetCode-Merged/Java/Building Outline.java new file mode 100644 index 0000000..8610681 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Building Outline.java @@ -0,0 +1,62 @@ +/* +Given N buildings in a x-axis,each building is a rectangle and can be represented by a triple (start, end, height),where start is the start position on x-axis, end is the end position on x-axis and height is the height of the building. Buildings may overlap if you see them from far away,find the outline of them。 + +An outline can be represented by a triple, (start, end, height), where start is the start position on x-axis of the outline, end is the end position on x-axis and height is the height of the outline. + +Example +Given 3 buildings: + +[ + [1, 3, 3], + [2, 4, 4], + [5, 6, 1] +] +The outlines are: + +[ + [1, 2, 3], + [2, 4, 4], + [5, 6, 1] +] +Note +Please merge the adjacent outlines if they have the same height and make sure different outlines cant overlap on x-axis. + +Tags Expand +LintCode Copyright Heap +*/ + + + +public class Solution { + /** + * @param buildings: A list of lists of integers + * @return: Find the outline of those buildings + */ + public ArrayList> buildingOutline(int[][] buildings) { + // write your code here + } +} + + +/* +Attempt1, may not be correct. +Thoughts: +PriorityQueue, sort by start. +1. Keep track of max height. +2. Find max height. +3. Poll() queue + a. on left of highest building, When height increate, record this point(x, height) + b. on right of highest building, when height decreses, record this point. + +*/ + + + + + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Burst Balloons.java b/Others/old records/LeetCode-Merged/Java/Burst Balloons.java new file mode 100644 index 0000000..ec05ba9 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Burst Balloons.java @@ -0,0 +1,121 @@ +其实会做之后挺好想的一个DP。 +dp[i][j] = balloons i~j 之间的sum. 然后找哪个点开始burst? 设为x。 +For loop 所有的点作为x, 去burst。 +每次burst都切成了三份:左边可以recusive 求左边剩下的部分的最大值 + 中间3项相乘 + 右边递归下去求最大值。 + + +这个是momorization, 而不纯是DP +因为recursive了,其实还是搜索,但是memorize了求过的值,节省了Processing +``` +/* +Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. +You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. +Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent. + +Find the maximum coins you can collect by bursting the balloons wisely. + +Note: +(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them. +(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 + +Example: + +Given [3, 1, 5, 8] + +Return 167 + + nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] + coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 +Credits: +Special thanks to @peisi for adding this problem and creating all test cases. + +Hide Company Tags Google +Show Tags +Divide and Conquer Dynamic Programming + + +*/ + +/* + Thoughts: as seen in dicussion. Build DP. + State: + dp[i][j]: the number of max coins can collect between i and j. + For a position x in [i,j], where to burst it? So this goes into a divide and conquer method. + Burst at x, track the sum, and record the max into dp[i][j] + Function: + dp[i][j] = Math.max(dp[i][j], DP(i, x-1) + nums[x-1]*nums[x]*nums[x+1] + DP(x+1, j)) + Init: + create dp[n+2][n+2]. (from 0 to n+1) + dp[0][1] = 1; + dp[n][n+1] = 1; + Return: + dp[1][n] + + DP(int i, int j, int[][] dp) + + Need to redo that nums. +*/ + + +public class Solution { + int[][] dp; + int[] values; + public int maxCoins(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int n = nums.length; + dp = new int[n + 2][n + 2]; + + //Initialize new array + values = new int[n + 2]; + values[0] = values[n + 1] = 1; + for (int i = 1; i < n + 1; i++) { + values[i] = nums[i - 1]; + } + + return DP(1, n); + } + + public int DP(int i, int j){ + if (dp[i][j] > 0) {//momorization + return dp[i][j]; + } + for (int x = i; x <= j; x++) { + dp[i][j] = Math.max(dp[i][j], DP(i, x - 1) + values[i-1]*values[x]*values[j+1] + DP(x + 1, j)); + } + return dp[i][j]; + } +} + +/* + 用了recursive + memorization, 但是也可以用传统的DP,比如: + for (int length = 1; length < n; length++) [ + for (int = 0; i < n-1; i++) { + j = i + length; + if length == 1: + dp[i][j] = A[i] * A[j] + A[i] + else: + dp[i][j] = max {} + } + } + +*/ + + + +/* + My Thought: TOO COMPLEX. Should go with the easy DP approach. Also, using a hashMap to trach all the patterns, + this might not be applicable: because as the integer array's length goes up, there will be too many possible + combinations to store in hashamp. + Burst each balloon, and DFS into each branch, calcualte the sum + each balloon-burst's product. + Also, use a HahsMap<"Value combination", max value>. to reduce the # of re-calculation. + convert nums into string, and in DFS, we don't even need bakc-tracking + helper(list, sum) + + + Thoughts:http://www.cnblogs.com/grandyang/p/5006441.html + dp[i,j]: burst range [i~j]'s max coins. + +*/ +``` diff --git a/Others/old records/LeetCode-Merged/Java/Closest Binary Search Tree Value.java b/Others/old records/LeetCode-Merged/Java/Closest Binary Search Tree Value.java new file mode 100644 index 0000000..865f7b0 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Closest Binary Search Tree Value.java @@ -0,0 +1,50 @@ +/* +Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. + +Note: +Given target value is a floating point. +You are guaranteed to have only one unique value in the BST that is closest to the target. + +Tags: Tree Binary Search +Similar Problems: (M) Count Complete Tree Nodes, (H) Closest Binary Search Tree Value II + +*/ + + +/* +Thoughts: +Binary search, maintain a closest value. +Note: initial closest in real case is just the root, since we start from the root +*/ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public int closestValue(TreeNode root, double target) { + if (root == null) { + return 0; + } + double closest = root.val; + while (root != null) { + if (root.val == target) { + return root.val; + } else { + if (Math.abs(target - closest) >= Math.abs(target - root.val)) { + closest = root.val; + } + if (root.val > target) { + root = root.left; + } else { + root = root.right; + } + } + }//END while + return (int)closest; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Count Primes.java b/Others/old records/LeetCode-Merged/Java/Count Primes.java new file mode 100644 index 0000000..7120d81 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Count Primes.java @@ -0,0 +1,83 @@ +什么是prime number: >=2的没有除自己和1以外公约数的数。 +还有另外一个中定义方法: +这个n,有没有小于n的一个i,而达到: i*i + # of i = n. 如果有,那就不是 prime。 + +方法很牛逼也很数学。没做的时候可能想不到。做了之后就觉得,哎,我去,有道理啊。 +简而言之:简历一个boolean长条,存isPrime[]。 然后从i=2, 全部变true. +然后利用这个因子的性质,非prime满足条件: self*self, self * self + self ... etc. +所以就check每一个j, j+i, j+i+i, 然后把所有non-prime全部mark成false. +最后,数一遍还剩下的true个数就好了 +``` +/* +Description: +Count the number of prime numbers less than a non-negative number, n. +Tags: Hash Table, Math +Similar Problems: (E) Ugly Number, (M) Ugly Number II, (M) Perfect Squares +*/ + +/* +Attempt2: https://leetcode.com/problems/count-primes/ explains it well +1. Ignore 1 and n. Don't count 1 and the number itself in. +2. Assume all numbers are prime in a boolean[]. Check off those are certainly not prime, the remaining will be prime. +3. For any n, only need to check up to i * i < n; more than that, for example 2 x 6 is same as checking 6x2, but 6x2 is not necessary to check. +4. How to mark things off: + The first non-prime is always i^2: self * self. + Then more non-primes:self * self, self * (self + 1), self * (self + 2) ... etc. + So, mark all of these index of in the boolean[] + +*/ +public class Solution { + public int countPrimes(int n) { + if (n <= 1) { + return 0; + } + boolean[] primes = new boolean[n]; + for (int i = 2; i < primes.length; i++) { + primes[i] = true; + } + + for (int i = 2; i * i< n; i++) { + if (!primes[i]) { + continue; + } + for (int j = i * i; j < n; j += i) { + primes[j] = false; + } + } + int count = 0; + for (int i = 2; i < primes.length; i++) { + count += primes[i] ? 1 : 0; + } + return count; + } +} + + +/*Timeout version*/ +//prime is a number n that cannot be divided by any number < n. +//In fact, only need to check sqrt(n) numbers from 1 + +public class Solution { + public int countPrimes(int n) { + int count = 0; + for (int i = 1; i < n; i++) { + if (isPrime(i)) { + count++; + } + } + return count; + } + + public boolean isPrime(int num) { + if (num <= 1) return false; + for (int i = 2; i * i <= num; i++) { + if (num % i == 0) { + return false; + } + } + return true; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Course Schedule II.java b/Others/old records/LeetCode-Merged/Java/Course Schedule II.java new file mode 100644 index 0000000..262c275 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Course Schedule II.java @@ -0,0 +1,101 @@ +详细的中文分析,看Course Schedule I +``` +/* +There are a total of n courses you have to take, labeled from 0 to n - 1. + +Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] + +Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses. + +There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array. + +For example: + +2, [[1,0]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course order is [0,1] + +4, [[1,0],[2,0],[3,1],[3,2]] +There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. +Both courses 1 and 2 should be taken after you finished course 0. +So one correct course order is [0,1,2,3]. Another correct ordering is[0,2,1,3]. + +Note: +The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. + +click to show more hints. + +Hints: +This problem is equivalent to finding the topological order in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses. +Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort. +Topological sort could also be done via BFS. +Hide Company Tags Facebook Zenefits +Hide Tags Depth-first Search Breadth-first Search Graph Topological Sort +Hide Similar Problems (M) Course Schedule (H) Alien Dictionary (M) Minimum Height Trees + +*/ + +/* + http://blog.csdn.net/ljiabin/article/details/45847019 + + Based on Course Schedule I, now we need to return all nodes with by the seq number. + + Note: + The map is built based on +*/ +public class Solution { + HashMap> map; + int[] visited; + int seq; + int[] order; + public int[] findOrder(int numCourses, int[][] prerequisites) { + order = new int[numCourses]; + seq = numCourses - 1; + visited = new int[numCourses]; + map = new HashMap>(); + //Put all start node into map. + for (int i = 0; i < prerequisites.length; i++) { + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new ArrayList()); + } + map.get(prerequisites[i][1]).add(prerequisites[i][0]); + } + //dfs on each start node in the pair + for (int i = 0; i < numCourses; i++) { + if (!dfs(i)) { + return new int[]{}; + } + } + return order; + } + + public boolean dfs (int node) { + if (visited[node] == 1) {//has been through this path, true. + return true; + } + if (visited[node] == -1) {//visiting a visited node from a deper level node, cycle + return false; + } + //mark it -1 then after dfs mark it 1. Marking and backtracking skills + visited[node] = -1; + + //Visit each child and make sure there is no cycle. + if (map.containsKey(node)) { + for (int nextNode : map.get(node)) { + if (!dfs(nextNode)) { + return false; + } + } + } + visited[node] = 1; + order[seq--] = node; + return true; + } + +} + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Course Schedule.java b/Others/old records/LeetCode-Merged/Java/Course Schedule.java new file mode 100644 index 0000000..b722c58 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Course Schedule.java @@ -0,0 +1,222 @@ +有点绕,但是做过一次就明白一点。 +是topological sort的题目。一般都是给有dependency的东西排序。 + +最终都会到一个sink node, 再不会有向后的dependency, 在那个点截止。 +我就已这样子的点为map的key, 然后value是以这个node为prerequisite的 list of courses. + +画个图的话,prerequisite都是指向那个sink node, 然后我们在组成map的时候,都是从sink node 发散回来到dependent nodes. + +在DFS里面,我们是反向的, 然后,最先完全visited的那个node, 肯定是最左边的node了,它被mark的seq也是最高的。 + +而我们的sink node,当它所有的支线都visit完了,seq肯定都已经减到最小了,也就是0,它就是第一个被visit的。 + + +``` +/* +There are a total of n courses you have to take, labeled from 0 to n - 1. + +Some courses may have prerequisites, for example to take course 0 you have to first take course 1, +which is expressed as a pair: [0,1] + +Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? + +For example: + +2, [[1,0]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible. + +2, [[1,0],[0,1]] +There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. +So it is impossible. + +Note: +The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. + +click to show more hints. + +Hints: +1. This problem is equivalent to finding if a cycle exists in a directed graph. + If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses. +2. Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort. +3. Topological sort could also be done via BFS. + +Hide Company Tags Zenefits +Hide Tags Depth-first Search Breadth-first Search Graph Topological Sort +Hide Similar Problems (M) Course Schedule II (M) Graph Valid Tree (M) Minimum Height Trees + +*/ + +/* + Thoughts: Try some help. make shorter version. + This version does not use a class, but does the exact same algorithm: mark visited and check cycle with dfs. + The idea is almost exaclty same (http://www.jyuan92.com/blog/leetcode-course-schedule/) + Instead of using a seq,visited to check mark seq, and visted, we can do a 'mark' backtracking. + This means: we can mark the visited = -1 before the dfs, and if anything in the dfs sees a -1, + it returns false; + After the dfs of children nodes in the map, wwe mark a node.visited = 1. That means the spot has been visited : ) + + Note: + SHould build he map: map +*/ + +public class Solution { + HashMap> map; + int[] visited; + public boolean canFinish(int numCourses, int[][] prerequisites) { + if (numCourses <= 0 || prerequisites == null || prerequisites.length == 0 || + prerequisites[0] == null || prerequisites[0].length == 0) { + return true; + } + visited = new int[numCourses]; + map = new HashMap>(); + //Put all start node into map. + for (int i = 0; i < prerequisites.length; i++) { + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new ArrayList()); + } + map.get(prerequisites[i][1]).add(prerequisites[i][0]); + } + //dfs on each start node in the pair + for (int i = 0; i < prerequisites.length; i++) { + if (!dfs(prerequisites[i][0])) { + return false; + } + } + + return true; + } + + public boolean dfs (int node) { + if (visited[node] == 1) {//has been through this path, true. + return true; + } + if (visited[node] == -1) {//visiting a visited node from a deper level node, cycle + return false; + } + //mark it -1 then after dfs mark it 1. Marking and backtracking skills + visited[node] = -1; + + //Visit each child and make sure there is no cycle. + if (map.containsKey(node)) { + for (int nextNode : map.get(node)) { + if (!dfs(nextNode)) { + return false; + } + } + } + + visited[node] = 1; + return true; + } + +} + + + + + + +/* + Thoughts: TO LONG. Should try shorter version. + ALSO, built the map based map: this will cause trouble and hard to work if we want to return + the sequence of course. + + Though, no need to find the correct order of course, but we can do Topological Sort via DFS, + where in the process we check if there is cycle. + 0. Create node {val, visited, list of child node}. OR: just a map + 1. Put all prerequisites in map + 2. For loop on all nodes in the map. + Each node, DFS on it, add all outgoing child on stack if that node is not visited + Check on cycle: after DFS on all child, we need to mark the parent node itself to be visited. + At this moment, if this node has been visited once, that means a cycle has happended, then return false; + + Implementation: + Use a node, track value, sequence number, and if visited, and its child nodes. + In DFS: first mark curr node visited, then DFS on child, then mark curr node with a sequence number. + Cycle: if a node has been visited but does not have a sequence number yet , + (that means some nodes at the earlier level, which has no been back-tracking to yet) + then there must be a cycle backwards. +*/ +public class Solution { + public class Node { + int val; + int seq; + boolean visited; + ArrayList children; + public Node(int val){ + this.val = val; + this.visited = false; + this.children = new ArrayList(); + this.seq = -1; + } + } + public int n; + public boolean canFinish(int numCourses, int[][] prerequisites) { + if (numCourses <= 0 || prerequisites == null || prerequisites.length == 0 || + prerequisites[0] == null || prerequisites[0].length == 0) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < prerequisites.length; i++) { + Node node; + //Add curr nodes + if (map.containsKey(prerequisites[i][0])) { + node = map.get(prerequisites[i][0]); + } else { + node = new Node(prerequisites[i][0]); + } + node.children.add(prerequisites[i][1]); + map.put(node.val, node); + //Add Child nodes + if (!map.containsKey(prerequisites[i][1])) { + map.put(prerequisites[i][1], new Node(prerequisites[i][1])); + } + } + n = prerequisites.length; + for (int i = 0; i < prerequisites.length; i++) { + if (!DFS(prerequisites[i][0], map)) { + return false; + } + } + + return true; + } + + public boolean DFS(int val, HashMap map) { + Node node = map.get(val); + node.visited = true; + map.put(val, node); + + for (int child : node.children) { + if (map.get(child).visited && map.get(child).seq == -1) {//Check cycle + return false; + } else if (!map.get(child).visited) { + if(!DFS(child, map)){ + return false; + } + } + } + + node.seq = n--; + map.put(val, node); + return true; + } +} + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Encode and Decode Strings.java b/Others/old records/LeetCode-Merged/Java/Encode and Decode Strings.java new file mode 100644 index 0000000..e445034 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Encode and Decode Strings.java @@ -0,0 +1,104 @@ + +不难,但是要考虑好如何handle ""。 +因为平时都把“” 当做Null对待,这里就犯浑了。 +这题,要把Null特别mark一下为‘NULL’,而特别处理 “” empty string. +``` +/* +Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings. + +Machine 1 (sender) has the function: + +string encode(vector strs) { + // ... your code + return encoded_string; +} +Machine 2 (receiver) has the function: +vector decode(string s) { + //... your code + return strs; +} +So Machine 1 does: + +string encoded_string = encode(strs); +and Machine 2 does: + +vector strs2 = decode(encoded_string); +strs2 in Machine 2 should be the same as strs in Machine 1. + +Implement the encode and decode methods. + +Note: +The string may contain any possible characters out of 256 valid ascii characters. Your algorithm should be generalized enough to work on any possible characters. +Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless. +Do not rely on any library method such as eval or serialize methods. You should implement your own encode/decode algorithm. + + +Tags: String +Similar Problems: (E) Count and Say, (M) Serialize and Deserialize Binary Tree + +*/ + +/* +Thoughts: +Break into integers +Use some special words to: 1. break line. 2. record null condition. +Note: "" empty string is also a string case, so don't treat that as null. Call null, "NULL" +Note2: As long as the list is not empty, though some string might be just "", make sure to encode it as 'LINE' just to remind in decoder: treat it as a "" +*/ +public class Codec { + // Encodes a list of strings to a single string. + public static String encode(List strs) { + if (strs == null || strs.size() == 0) { + return "NULL"; + } + StringBuffer sb = new StringBuffer(); + for (String str : strs) { + char[] arr = str.toCharArray(); + for (int i = 0; i < arr.length; i++) { + if (arr[i] >= 100) { + sb.append("" + (int)arr[i]); + } else if (arr[i] >= 10) { + sb.append("0" + (int)arr[i]); + } else { + sb.append("00" + (int)arr[i]); + } + } + sb.append("LINE"); + }//END for + if (sb.length() == 0) { + sb.append("LINE"); + } + return sb.toString(); + } + + // Decodes a single string to a list of strings. + public static List decode(String s) { + List rst = new ArrayList(); + if (s.equals("NULL")) { + return rst; + } + int index = s.indexOf("LINE"); + while (index != -1) { + String str = s.substring(0, index); + + StringBuffer sb = new StringBuffer(); + int i = 0; + while (i + 3 <= str.length()) { + int letter = Integer.parseInt(str.substring(i, i + 3)); + sb.append((char)letter); + i+=3; + } + rst.add(sb.toString()); + + s = s.substring(index + 4); + index = s.indexOf("LINE"); + } + + return rst; + } +} +// Your Codec object will be instantiated and called as such: +// Codec codec = new Codec(); +// codec.decode(codec.encode(strs)); + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Excel Sheet Column Number.java b/Others/old records/LeetCode-Merged/Java/Excel Sheet Column Number.java new file mode 100644 index 0000000..fa6385a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Excel Sheet Column Number.java @@ -0,0 +1,46 @@ +好久以前做的一个题了。 +记得:'A' - 'A' = 0 呀。所以 any char - 'A' + 1 = 这个char在我们这个题目里面所代表的数字。 +其次,26个字母代表着26位运算。和10位一样嘛,那第一位x26就好了。 +``` +/* + +Given a column title as appear in an Excel sheet, return its corresponding column number. + +For example: + + A -> 1 + + B -> 2 + + C -> 3 + + ... + + Z -> 26 + + AA -> 27 + + AB -> 28 + +*/ + +public class Solution {//ABC -> 'A', 'B', 'C' + +public int titleToNumber(String s) {//S = AA + +int rst = 0; + +char[] arr = s.toCharArray(); + +for (int i = 0; i < arr.length; i++) {//i = 0,1,2 // (char c : arr) + +rst = rst * 26 + arr[i] - 'A' + 1;//rst =1, 26 + 1 = 27, + +} + +return rst; + +} + +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/ExcelSheetColumnNumber .java b/Others/old records/LeetCode-Merged/Java/ExcelSheetColumnNumber .java new file mode 100644 index 0000000..c5db099 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/ExcelSheetColumnNumber .java @@ -0,0 +1,25 @@ +/* +Given a column title as appear in an Excel sheet, return its corresponding column number. + +For example: + + A -> 1 + B -> 2 + C -> 3 + ... + Z -> 26 + AA -> 27 + AB -> 28 +*/ + + +public class Solution {//ABC -> 'A', 'B', 'C' + public int titleToNumber(String s) {//S = AA + int rst = 0; + char[] arr = s.toCharArray(); + for (int i = 0; i < arr.length; i++) {//i = 0,1,2 // (char c : arr) + rst = rst * 26 + arr[i] - 'A' + 1;//rst =1, 26 + 1 = 27, + } + return rst; + } +} diff --git a/Others/old records/LeetCode-Merged/Java/Find Peak Element.java b/Others/old records/LeetCode-Merged/Java/Find Peak Element.java new file mode 100644 index 0000000..5ca799b --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Find Peak Element.java @@ -0,0 +1,52 @@ +/* +A peak element is an element that is greater than its neighbors. + +Given an input array where num[i] ≠ num[i+1], find a peak element and return its index. + +The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. + +You may imagine that num[-1] = num[n] = -∞. + +For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2. + +Note: +Your solution should be in logarithmic complexity. + +Tags: Array, Binary Search + +*/ + +/* +Thoughts: +Easy brutle force: pick any element, see it's increasing or decresing, then move forward the increasing directin. O(n) +Here, try binary search method +Note: Special case of 3 element, which could run into infinite loop, so check start + 1 < end. (That is, when start, mid, end are 3 adjacent increasing/decresing point, they will run into infinite loop) + +Note2: because of missing case, 1,0,1 case when mid is at '0'. It needs either direction. +*/ +public class Solution { + public int findPeakElement(int[] nums) { + if (nums == null || nums.length <= 1) { + return 0; + } + int start = 0; // 0 + int end = nums.length - 1;// 2 + int mid; + while (start + 1 < end) { + mid = start + (end - start)/2;//1 + if (mid <= 0 || mid >= nums.length - 1) {//start and end are adjacent, jump to end + break; + } + if (nums[mid - 1] < nums[mid] && nums[mid] > nums[mid + 1]) { + return mid; + } else if (nums[mid - 1] < nums[mid] && nums[mid] < nums[mid + 1]) { + start = mid + 1; + } else if (nums[mid - 1] > nums[mid] && nums[mid] > nums[mid + 1]) { + end = mid - 1; + } else {//1,0,1 case + end = mid - 1; + } + }//end while + return nums[start] > nums[end] ? start : end; + } +} diff --git a/Others/old records/LeetCode-Merged/Java/First Bad Version.java b/Others/old records/LeetCode-Merged/Java/First Bad Version.java new file mode 100644 index 0000000..e9e2e62 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/First Bad Version.java @@ -0,0 +1,43 @@ +这个挺直接的,也被李特标了EASY. +就是在1~n里面找第一个出错点。其实就是搜一个数字i(同时用isBadVersion(i))检查这个数字是否报错。那搜index的活,直接binary search就好了。 +注意特别条件: +``` +!isBadVersion(i) && isBadVersion(i+1) +``` +一定要找出这个i+1,就是第一个出错点。 + +还有就是:很可能start == end了呀,如果还没有完结,那么最终的那个情况必然是start==end==mid, 然后既然mid之前没找到错,那么try 一try isBadVersion(mid) 就好了。 +``` +/* +You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad. + +Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad. + +You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API. +*/ + +/* The isBadVersion API is defined in the parent class VersionControl. + boolean isBadVersion(int version); */ + +public class Solution extends VersionControl { + public int firstBadVersion(int n) { + if (n <= 1) { + return isBadVersion(n) ? n : -1; + } + int start = 1; + int end = n; + int mid = start + (end - start) / 2; + while(start < end) { + mid = start + (end - start) / 2; + if (!isBadVersion(mid) && isBadVersion(mid + 1)) { + return mid + 1; + } else if (!isBadVersion(mid)){ + start = mid; + } else { + end = mid; + } + } + return isBadVersion(mid) ? mid : -1; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Flatten 2D Vector.java b/Others/old records/LeetCode-Merged/Java/Flatten 2D Vector.java new file mode 100644 index 0000000..10cfaee --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Flatten 2D Vector.java @@ -0,0 +1,82 @@ +/* +Implement an iterator to flatten a 2d vector. + +For example, +Given 2d vector = + +[ + [1,2], + [3], + [4,5,6] +] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]. + +Hint: + +How many variables do you need to keep track? +Two variables is all you need. Try with x and y. +Beware of empty rows. It could be the first few rows. +To write correct code, think about the invariant to maintain. What is it? +The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? +Not sure? Think about how you would implement hasNext(). Which is more complex? +Common logic in two different places should be refactored into a common method. + + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Zigzag Iterator, (M) Peeking Iterator + +*/ + +/* +Thoughts: +As hint indicates: use 2 pointers to hold position. +Use hasNext to validate (x,y) and move x. +Use next() to return (x,y) and move it(regardless of correctness, which is determined by hasNext()) +*/ +public class Vector2D { + private int x; + private int y; + private List> list; + public Vector2D(List> vec2d) { + if (vec2d == null) { + return; + } + this.x = 0; + this.y = 0; + this.list = vec2d; + } + + public int next() { + int rst = list.get(x).get(y); + if (y + 1 >= list.get(x).size()) { + y = 0; + x++; + } else { + y++; + } + return rst; + } + + public boolean hasNext() { + if (list == null) { + return false; + } + while (x < list.size() && list.get(x).size() == 0) { + x++; + y = 0; + } + if (x >= list.size()) { + return false; + } + if (y >= list.get(x).size()) { + return false; + } + return true; + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D i = new Vector2D(vec2d); + * while (i.hasNext()) v[f()] = i.next(); + */ \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Flattern 2D Vector.java b/Others/old records/LeetCode-Merged/Java/Flattern 2D Vector.java new file mode 100644 index 0000000..cc01237 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Flattern 2D Vector.java @@ -0,0 +1,88 @@ +大概意思就是把2D list里面的element全部遍历一遍。 +注意啊,一开始理解题意搞错:我以为是必须要排序正确,所以上来就PriorityQueue+HashMap搞得无比复杂。其实,这个跟一个nxn的matrix遍历,是没区别的拉。 +所有来个x,y,把2d list跑一变。 + +``` +/* +Implement an iterator to flatten a 2d vector. + +For example, +Given 2d vector = + +[ + [1,2], + [3], + [4,5,6] +] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]. + +Hint: + +How many variables do you need to keep track? +Two variables is all you need. Try with x and y. +Beware of empty rows. It could be the first few rows. +To write correct code, think about the invariant to maintain. What is it? +The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? +Not sure? Think about how you would implement hasNext(). Which is more complex? +Common logic in two different places should be refactored into a common method. + + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Zigzag Iterator, (M) Peeking Iterator + +*/ + +/* +Thoughts: +As hint indicates: use 2 pointers to hold position. +Use hasNext to validate (x,y) and move x. +Use next() to return (x,y) and move it(regardless of correctness, which is determined by hasNext()) +*/ +public class Vector2D { + private int x; + private int y; + private List> list; + public Vector2D(List> vec2d) { + if (vec2d == null) { + return; + } + this.x = 0; + this.y = 0; + this.list = vec2d; + } + + public int next() { + int rst = list.get(x).get(y); + if (y + 1 >= list.get(x).size()) { + y = 0; + x++; + } else { + y++; + } + return rst; + } + + public boolean hasNext() { + if (list == null) { + return false; + } + while (x < list.size() && list.get(x).size() == 0) { + x++; + y = 0; + } + if (x >= list.size()) { + return false; + } + if (y >= list.get(x).size()) { + return false; + } + return true; + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D i = new Vector2D(vec2d); + * while (i.hasNext()) v[f()] = i.next(); + */ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Flip Game II.java b/Others/old records/LeetCode-Merged/Java/Flip Game II.java new file mode 100644 index 0000000..3fb9bff --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Flip Game II.java @@ -0,0 +1,171 @@ +12.06.2015 recap: +注意:不要乱改input s. recursive call 需要用原始的input s. + +这个题目李特是屌炸天的。 +我飞了九牛二虎之力(路子对),但是代码写的七荤八素,好长好长好长好长的。 +结果正解,三四行就搞定了。真是心有不甘啊。 +想法如下: +保证p1能胜利,就必须保持所有p2的move都不能赢。 +同时,p1只要在可走的Move里面,有一个move可以赢就足够了。 +(题目里面用一个for loop + 只要 满足条件就return true来表达 OR的意思:p1不同的路子,赢一种就行了) +p1: player1 +p2: player2 + +``` +/* +You are playing the following Flip Game with your friend: +Given a string that contains only these two characters: + and -, +you and your friend take turns to flip two consecutive "++" into "--". +The game ends when a person can no longer make a move and therefore the other person will be the winner. + +Write a function to determine if the starting player can guarantee a win. + +For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+". + +Follow up: +Derive your algorithm's runtime complexity. + +Tags: Backtracking +Similar Problems: (E) Nim Game, (E) Flip Game +*/ + +/* + recap: 12.06.2015 + Make sure to use a new string, and do not alter the original input s when calling recursively on canWin. +*/ + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + String str = new String(s); + while (str.indexOf("++") != -1) { + int index = str.indexOf("++"); + if(!canWin(s.substring(0, index) + "--" + s.substring(index + 2))) { + return true; + } + str = str.substring(0, index) + "-" + str.substring(index + 1); + } + return false; + } + +} + + + +/* +Attemp2, from:http://www.cnblogs.com/jcliBlogger/p/4886741.html +Similar to my idea, but much more clear: no need of the isP1 flag. +Iterative idea:p1 can win, and p2 must not win at all. +Therefore, if p2's move can't win, we return true on p1's state. +For loop and the if statement works as 'OR': just need one of the p1's movement win. +*/ + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (!canWin( s.substring(0, i) + "--" + s.substring(i + 2))) {//Just pick one way of p1's move + return true; + } + str = str.substring(0, i) + "-" + str.substring(i + 1);//Help to move certain spot. + } + return false; + } + +} +//let k = n/2 +//O(k * (k - 1) * (k - 2) ... k) = O(k!) = O((n/2)!) = O(n!) + +/* +Attempt1, Failed. +Thoughts: +method checkP1Win(), inside of it: +OR all p1's win state, if one of the move wins, return true; +However, a bit of code redundancy, does not feel good about this. +Fails on "+++++++++" +*/ +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + boolean rst = false; + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (checkP1Win(s, i, true)) { + rst = true; + break; + } + str = str.substring(0, i) + "-" + str.substring(i + 1); + } + return rst; + + } + public static boolean checkP1Win(String str, int x, boolean isP1) { + String s = str.substring(0,x) + "--" + str.substring(x + 2); + if (s.indexOf("++") == -1) { + return isP1; + } + for (int i = s.indexOf("++"); i >= 0 && i < s.length() - 1; i = s.indexOf("++")) { + if (checkP1Win(s, i, !isP1)) { + return true; + } + s = s.substring(0, i) + "-" + s.substring(i + 1); + } + return false; + } + + +} + + + +public class Solution { + public static boolean canWin(String s) { + if (s == null || s.length() <= 1) { + return false; + } + boolean rst = false; + String str = new String(s); + for (int i = str.indexOf("++"); i >= 0 && i < str.length() - 1; i = str.indexOf("++")) { + if (checkP1Win(s, i, true)) { + rst = true; + break; + } + str = str.substring(0, i) + "-" + str.substring(i + 1); + } + return rst; + + } + public static boolean checkP1Win(String str, int x, boolean isP1) { + String s = str.substring(0,x) + "--" + str.substring(x + 2); + if (s.indexOf("++") == -1) { + return isP1; + } + if (isP1) { + String temp = s; + for (int i = temp.indexOf("++"); i >= 0 && i < temp.length() - 1; i = temp.indexOf("++")) { + if (checkP1Win(s, i, !isP1)) { + return true; + } + temp = temp.substring(0, i) + "-" + temp.substring(i + 1); + } + return false; + } else { + String temp = s; + for (int i = temp.indexOf("++"); i >= 0 && i < temp.length() - 1; i = temp.indexOf("++")) { + if (!checkP1Win(s, i, !isP1)) { + return false; + } + temp = temp.substring(0, i) + "-" + temp.substring(i + 1); + } + return true; + } + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Flip Game.java b/Others/old records/LeetCode-Merged/Java/Flip Game.java new file mode 100644 index 0000000..2afa5c1 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Flip Game.java @@ -0,0 +1,78 @@ +这个题目是很寂寞的. 2 pointer可以做, 在网上又搜了一下,貌似可以有很多牛逼的优化,我暂时还没去看。 +很郁闷的就是条件不明,原来只需要从'++'转到'--'的情况,反过来没必要关注...搞了我半天啊 +``` +/* +You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner. + +Write a function to compute all possible states of the string after one valid move. + +For example, given s = "++++", after one move, it may become one of the following states: + +[ + "--++", + "+--+", + "++--" +] +*/ + +// 12.06.2015, slower than the previous one +public class Solution { + public List generatePossibleNextMoves(String s) { + List rst = new ArrayList(); + if (s == null || s.length() == 0) { + return rst; + } + ArrayList list = new ArrayList(); + StringBuffer sb = new StringBuffer(s); + while (sb.indexOf("++") != -1) { + int index = sb.indexOf("++"); + list.add(index); + sb.replace(index, index + 1, "*"); + } + for (int index : list) { + rst.add(s.substring(0, index) + "--" + s.substring(index + 2)); + } + return rst; + } +} + + +/* +Thoughts: +Two pointers to check if p1 and p2 match target patern. If so, add. + +Need to ask: are we only looking to change to '--' from '++'? +*/ +public class Solution { + public static List generatePossibleNextMoves(String s) { + List rst = new ArrayList(); + if (s == null || s.length() < 1) { + return rst; + } + char[] arr = s.toCharArray(); + search('+','-',arr,rst); + return rst; + } + + public static void search(char target, char replace, char[] arr, List rst) { + int p1 = 0; + int p2 = 1; + while (p2 <= arr.length - 1) { + if (arr[p1] == target && arr[p2] == target) { + arr[p1] = replace; + arr[p2] = replace; + rst.add(new String(arr)); + arr[p1] = target; + arr[p2] = target; + } + p1++; + p2++; + } + } +} + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Fraction to Recurring Decimal.java b/Others/old records/LeetCode-Merged/Java/Fraction to Recurring Decimal.java new file mode 100644 index 0000000..d482da0 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Fraction to Recurring Decimal.java @@ -0,0 +1,121 @@ +不难想到处理除法:考虑正负,考虑小数点前后。主要是小数点以后的要着重考虑。 +很容易忽略的是integer的益处。 +``` +/* +Given two integers representing the numerator and denominator of a fraction, return the fraction in string format. + +If the fractional part is repeating, enclose the repeating part in parentheses. + +For example, + +Given numerator = 1, denominator = 2, return "0.5". +Given numerator = 2, denominator = 1, return "2". +Given numerator = 2, denominator = 3, return "0.(6)". + +Hide Company Tags Google +Show Tags +Hash Table Math + + +*/ + +/* + Thoughts: + Divide it into small pieces: + 1. d = 0, return null; + 2. n = 0 -> 0 + 3. mark negative. let n = abs(numerator), d = abs(denominator) + 4. consider front and end: + front = (int)sharp divide + end: build hashmap to track if the numerator*10 occurs. Once occurs again, return the remianing. + 5. based on sign, return results. + +Note: +Have to take int overflow INT_MAX, INT_MIN.... +*/ +//Optimized code: +public class Solution { + public String fractionToDecimal(int numerator, int denominator) { + long nume = Math.abs((long)numerator); + long deno = Math.abs((long)denominator); + String sign = (numerator < 0) ^ (denominator < 0) ? "-" : ""; + if (deno == 0) { + return ""; + } else if (nume == 0) { + return "0"; + } else if (nume % deno == 0) { + return sign + nume/deno + ""; + } + + HashMap map = new HashMap(); + StringBuffer rst = new StringBuffer(sign + nume/deno + "."); + long end = nume%deno * 10;//The decimal portion of the value, after decimal point + int i = 0; + while (end != 0){ + if (map.containsKey(end)) { + rst.insert(rst.indexOf(".") + map.get(end) + 1, "("); + rst.append(")"); + return rst.toString(); + } + rst.append(end/deno); + map.put(end, i++); + end = (end % deno) * 10; + } + return rst.toString(); + } +} + + + +//Original working version +public class Solution { + public String fractionToDecimal(int numerator, int denominator) { + long nume = Math.abs((long)numerator); + long deno = Math.abs((long)denominator); + String sign = (numerator < 0) ^ (denominator < 0) ? "-" : ""; + if (deno == 0) { + return ""; + } else if (nume == 0) { + return "0"; + } else if (nume % deno == 0) { + return sign + nume/deno + ""; + } + + String rst = sign + nume/deno + "."; + long end = nume%deno * 10; + + HashMap map = new HashMap(); + boolean repeat = false; + String endRepeat = ""; + int n = 0; + while (true){ + if (end == 0) { + break; + } else if (map.containsValue(end)) { + repeat = true; + break; + } + map.put(n++, end); + end = (end % deno) * 10; + } + + for (int i = 0; i < n; i++) { + if (repeat && map.get(i) == end) { + rst += "(" + map.get(i)/deno; + endRepeat = ")"; + repeat = false; + } else { + rst += map.get(i)/deno; + } + } + + return rst + endRepeat; + } +} + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Game of Life.java b/Others/old records/LeetCode-Merged/Java/Game of Life.java new file mode 100644 index 0000000..2799713 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Game of Life.java @@ -0,0 +1,42 @@ +/* +According to the Wikipedia's article: +"The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970." + +Given a board with m by n cells, each cell has an initial state live (1) or dead (0). +Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules +(taken from the above Wikipedia article): + +Any live cell with fewer than two live neighbors dies, as if caused by under-population. +Any live cell with two or three live neighbors lives on to the next generation. +Any live cell with more than three live neighbors dies, as if by over-population.. +Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction. +Write a function to compute the next state (after one update) of the board given its current state. + +Follow up: +Could you solve it in-place? Remember that the board needs to be updated at the same time: +You cannot update some cells first and then use their updated values to update other cells. +In this question, we represent the board using a 2D array. + In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. + How would you address these problems? +Credits: +Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. + +Hide Company Tags Google TinyCo +Hide Tags Array +Hide Similar Problems (M) Set Matrix Zeroes + +*/ + +/* + Thoughts: + https://segmentfault.com/a/1190000003819277 + http://my.oschina.net/Tsybius2014/blog/514447 + build state machine. + take mod of 2 at the end. +*/ + +public class Solution { + public void gameOfLife(int[][] board) { + + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Generate Parentheses.java b/Others/old records/LeetCode-Merged/Java/Generate Parentheses.java new file mode 100644 index 0000000..bba7814 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Generate Parentheses.java @@ -0,0 +1,73 @@ +/* +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: + +"((()))", "(()())", "(())()", "()(())", "()()()" + +Hide Company Tags Google Zenefits +Hide Tags Backtracking String +Hide Similar Problems (M) Letter Combinations of a Phone Number (E) Valid Parentheses + +*/ + +/* + Thoughts: + Pick ( or not. + Pick ) or not. + Back tracking. + when #"(" and #")" are both n, return the result. +*/ +public class Solution { + public List generateParenthesis(int n) { + List rst = new ArrayList(); + if (n <= 0) { + return rst; + } + ArrayList list = new ArrayList(); + helper(rst, list, 0, 0, n); + + return rst; + } + + public void helper(List rst, ArrayList list, + int left, int right, int n) { + if (left == n && right == n) { + StringBuffer sb = new StringBuffer(); + for (String s : list) { + sb.append(s); + } + rst.add(sb.toString()); + return; + } + //add ( + if (left < n) { + list.add("("); + helper(rst, list, left + 1, right, n); + list.remove(list.size() - 1); + } + //add ) + if (right < left) { + list.add(")"); + helper(rst, list, left, right + 1, n); + list.remove(list.size() - 1); + } + } +} + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Graph Valid Tree.java b/Others/old records/LeetCode-Merged/Java/Graph Valid Tree.java new file mode 100644 index 0000000..2838d70 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Graph Valid Tree.java @@ -0,0 +1,87 @@ +/* +Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), +write a function to check whether these edges make up a valid tree. + +For example: + +Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true. + +Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false. + +Hint: + +Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], what should your return? Is this case a valid tree? +According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. +In other words, any connected graph without simple cycles is a tree.” +Note: you can assume that no duplicate edges will appear in edges. +Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + +Hide Company Tags Google Facebook Zenefits +Hide Tags Depth-first Search Breadth-first Search Graph Union Find +Hide Similar Problems (M) Course Schedule + +*/ + +/* + Thoughts: + The edge here has no directin. + The goal is to check if the graphc is connected && if there is cycle. + Do union-find. + Check each pair: If they are in the same set: do they share same parent? + If they do, that makes a triangle between this node elementsi the pair and their parent. That is a cycle. False. + If no common parent, union them into 1 set. + + find(x): recursively set the current node equals to it's parent node's parent's parent's .... partent's node. + Via just 1 call to x, it will update all parent nodes to equal to the root parent lol +*/ + + +public class Solution { + int[] parents; + public boolean validTree(int n, int[][] edges) { + //edges can be [], when n == 1, it'll be true. + if (edges.length != n - 1) { + return false; + } + parents = new int[n]; + //Init + for (int i = 0; i < parents.length; i++) { + parents[i] = i; + } + //Use union-find to detect if pair has common parents, and merge then to 1 set + for (int i = 0; i < edges.length; i++){ + if (find(edges[i][0]) == find(edges[i][1])) { + return false; + } + union(edges[i][0], edges[i][1]); + } + + return true; + } + + /* + Not only find parent, also update the spot parents[node] with parent node, recursively. + */ + public int find(int node) { + if (parents[node] == node) { + return node; + } + parents[node] = find(parents[node]); + return parents[node]; + } + + public void union(int x, int y) { + int findX = parents[x]; + int findY = parents[y]; + if (findX != findY) { + parents[findX] = findY; + } + } +} + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Gray Code.java b/Others/old records/LeetCode-Merged/Java/Gray Code.java new file mode 100644 index 0000000..e6287cf --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Gray Code.java @@ -0,0 +1,144 @@ +李特这特题目有点蛋疼,因为目前只接受一种结果。 +我做的恰好和它要的结果不一样,但是我觉得我这种走法走出来也是没错的。 +基本想法就是从一个点开始往一个方向走,每次flip一个bit, 碰壁的时候就回头走。 +``` +/* + +The gray code is a binary numeral system where two successive values differ in only one bit. + +Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. + +For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: + +00 - 0 + +01 - 1 + +11 - 3 + +10 - 2 + +Note: + +For a given n, a gray code sequence is not uniquely defined. + +For example, [0,2,3,1] is also a valid gray code sequence according to the above definition. + +For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that. + +Tags:Backtracking + +*/ + +/* + +Leetcode tags shows backtracking. That should be different approach than what I hvae below: + +*/ + +/* + +TRY: My code works for this run-through, however does not fit the OJ yet + +0 0 0 [start, noting happend, flip index 0] + +0 0 <-1 [move to flip left adjacent] + +0 <-1 1 [move to flip left adjacent] + +1-> 1 1 [move to flip right adjacent] + +1 0-> 1 [move to flip right adjacent] + +1 0 <-0 [move to flip left adjacent] + +1 <-1 0 [move to flip left adjacent] + +0 1 0 [done] + +Conclusion: hit the wall and flip the other direction. + +Every flip, add integer to list + +Convert the char[] to string, then Integer.parse(str, 2) to integer + +Simulate the steps: + +For example, when n = 3, step = n - 1. It takes 2 steps from right side to reach left side, it hits the wall and turn around. + +Now: + +1. Initialize char[] and add '000' + +2. do for loop on 1 ~ 2^n -2. last step '010' is stepped into, but no further action, so take 2^3 - 1 = 7 steps. + +*/ + +public class Solution { + +public List grayCode(int n) { + +List rst = new ArrayList(); + +if (n < 0) { + +return rst; + +} + +char[] bits = new char[n]; + +for (int i = 0; i < bits.length; i++) { + +bits[i] = '0'; + +} + +String str = new String(bits); + +if (n == 0) { + +str = "0"; + +} + +rst.add(Integer.parseInt(str, 2)); + +int step = n - 1; + +boolean LR = true;//L: true; R: false + +int steps = (int)Math.pow(2, n) - 1; + +for (int i = 0; i < steps; i++) { + +bits[step] = bits[step] == '0' ? '1' : '0'; + +str = new String(bits); + +rst.add(Integer.parseInt(str, 2)); + +if (LR) { + +step--; + +} else { + +step++; + +} + +if (step == (n - 1) || step == 0) {//Turn around + +LR = !LR; + +} + +} + +return rst; + +} + +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Group Anagrams.java b/Others/old records/LeetCode-Merged/Java/Group Anagrams.java new file mode 100644 index 0000000..f2aff48 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Group Anagrams.java @@ -0,0 +1,62 @@ +/* +Given an array of strings, group anagrams together. + +For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], +Return: + +[ + ["ate", "eat","tea"], + ["nat","tan"], + ["bat"] +] +Note: +For the return value, each inner list's elements must follow the lexicographic order. +All inputs will be in lower-case. +Update (2015-08-09): +The signature of the function had been updated to return list> instead of list, as suggested here. If you still see your function signature return a list, please click the reload button to reset your code definition. + +Tags: Hash Table String +Similar Problems: (E) Valid Anagram, (E) Group Shifted Strings + +*/ + +/* +Thoughts: +Store the anagram in a order list. Collections.sort it. +Store all the anagram strings into +Colelction.sort all lists and put them into final result. + +Note: use Arrays.sort() to sort string. +Note2: can do (element : array, arraylist) in for loop + +*/ +public class Solution { + public List> groupAnagrams(String[] strs) { + List> rst = new ArrayList>(); + if (strs == null) { + return rst; + } + + List order = new ArrayList(); + HashMap> map = new HashMap>(); + for (String str : strs) { + char[] arr = str.toCharArray(); + Arrays.sort(arr); + String s = new String(arr); + if (!map.containsKey(s)){ + List l = new ArrayList(); + l.add(str); + order.add(s); + map.put(s, l); + } else { + map.get(s).add(str); + } + } + Collections.sort(order); + for (String str : order) { + Collections.sort(map.get(str)); + rst.add(map.get(str)); + } + return rst; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/H-Index II.java b/Others/old records/LeetCode-Merged/Java/H-Index II.java new file mode 100644 index 0000000..ec03820 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/H-Index II.java @@ -0,0 +1,59 @@ +H-index的一个优化。 +binary search +``` +/* +Follow up for H-Index: What if the citations array is sorted in ascending order? +Could you optimize your algorithm? +Hint: + +Expected runtime complexity is in O(log n) and the input is sorted. + +Hide Company Tags Facebook +Hide Tags Binary Search +Hide Similar Problems (M) H-Index + +*/ + +/* + citations[0,1,3,5,6] + look for a h, where x = N-h, arr[x] >= h + h is from right ot left. + We want to find smallest x that has arr[x] >= n-x + binary search: + start,mid,end + if match, keep going left until not able to + O(nLogN) +*/ + +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + int n = citations.length; + int start = 0; + int end = n - 1; + int mid; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (citations[mid] == n - mid) { + if (mid - 1 >= 0 && citations[mid - 1] == n - (mid-1)) { + end = mid; + } else { + return n - mid;// that is n - x + } + } else if (citations[mid] < n - mid) { + start = mid; + } else { + end = mid; + } + } + if (citations[start] >= n - start) { + return n - start; + } else if (citations[end] >= n - end) { + return n - end; + } + return 0; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/H-Index.java b/Others/old records/LeetCode-Merged/Java/H-Index.java new file mode 100644 index 0000000..d062c09 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/H-Index.java @@ -0,0 +1,111 @@ +例子写出来,发现可以sort以后按照定义搜索一遍。 nlogn. + 当然,搜索一遍时候可以优化,用binary search. 但是没意义,因为array.sort已经用了nlogn + +o(n)也可以,用bucket. 比较巧妙。 + + +``` +/* +Given an array of citations (each citation is a non-negative integer) of a researcher, +write a function to compute the researcher's h-index. + +According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers +have at least h citations each, +and the other N − h papers have no more than h citations each." + +For example, given citations = [3, 0, 6, 1, 5], which means the researcher has 5 papers in total and +each of them had received 3, 0, 6, 1, 5 citations respectively. +Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, his h-index is 3. + +Note: If there are several possible values for h, the maximum one is taken as the h-index. + +Hint: + +An easy approach is to sort the array first. +What are the possible values of h-index? +A faster approach is to use extra space. + +Google Facebook +Hide Tags Hash Table Sort +Hide Similar Problems (M) H-Index II + +*/ + +/* + Thoughts:O(nlogn) + N = 5, so max of h = 5. min of h = 0. + 1. h = 5, loop through the array and count the # of citations that are >= h. + 2 .h = 4 ... h=1, h=0. + => O(n^2). + + If sort it : 0,1,3,5,6 + Find find index x = N - h, and arr[x] >= h + that becomes find index x that arr[x] >=h ,where h = N - x. + Foor loop on h, O(n) + pick x = N - h, and check if arr[x] >= h + h = 5, x = 5 -5 = 0. arr[x] = 0 < h. not working + h = 4, x = 5 - 4 = 1. arr[x] = 1. no. + h=3,x=5-3 =2,arr[x]=3 3>=3, okay. + nLogn + N = O(nlogn) + + +*/ +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + Arrays.sort(citations); + for (int h = citations.length; h > 0; h--) { + int x = citations.length - h; + if (citations[x] >= h) { + return h; + } + } + return 0; + } +} + + +/* + Thoughts: as the hint shows, use extra space and make it faster. + citations = [3, 0, 6, 1, 5], + (http://buttercola.blogspot.com/2015/09/leetcode-h-index.html?_sm_au_=iHVFjb76ZHj7ND5D) + 1. For loop to count++ in correct buttkit regardless of the index. + If arr[x] <= n, then bucket[arr[x]]++. that means, the bucket with index of arr[x] should store this arr[x] element. + If arr[x] > n, well, that means it exceeds bucket.length (in this application, it means it's already greater than the max of h=n) + so let's just put it in bucket[n]++. + Obvisouly, we need bucket[n + 1] + 2. Each bucket slot now stores #of values that's >= it's index h, in ascending order ofcourse. + so we can do another for loop, to sum one by one, from h = n ~ 0, (because we need higest possible h) + if sum >= h, that is the rst. +*/ +public class Solution { + public int hIndex(int[] citations) { + if (citations == null || citations.length == 0) { + return 0; + } + int n = citations.length; + int[] bucket = new int[n + 1]; + //fill bucket + for (int i = 0; i < n; i++) { + int bucketSlot = citations[i]; + if (citations[i] <= n) { + bucket[bucketSlot]++; + } else {//bucketSlot > n + bucket[n]++; + } + } + + //Find best H + int sum = 0; + for (int h = n; h >= 0; h--) { + if (sum + bucket[h] >= h) { + return h; + } + sum += bucket[h]; + } + return 0; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Implement Trie (Prefix Tree).java b/Others/old records/LeetCode-Merged/Java/Implement Trie (Prefix Tree).java new file mode 100644 index 0000000..9f0f47b --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Implement Trie (Prefix Tree).java @@ -0,0 +1,111 @@ +Trie自己不多用到。 +如果是遇到一个一个字查询的题,可以考虑一下。 +构建TrieNode的时候要注意:如何找孩子?如果是个map的话,其实就挺好走位的。 +而且,每个node里面的 char 或者string有时候用处不大, +可以为空。但是有些题目,比如在结尾要return一些什么String,就可以在end string那边存一个真的String。 + + +``` +/* +Implement a trie with insert, search, and startsWith methods. + +Note: +You may assume that all inputs are consist of lowercase letters a-z. + +Tags: Trie Design +Similar Problems: (M) Add and Search Word - Data structure design + +*/ +/* +Thoughts: +Understand how prefix tree works, create TrieNode() smartly. (http://www.cnblogs.com/tonyluis/p/4563990.html) +Insert: whenever node does not exist, create a new node. +Search: search through each node, if any node not exist, false; at the end, that node has to be end of that path. +StartWith: very similar to search; at the end, as long as all nodes appear through the path, just return true. + +Note: +The contents of the TrieNode can be just a char, or it can be empty String except the end string: for that case +when we need return the end string. +Also, search and startWith is quite similar, remember that. +*/ + +class TrieNode { + char c; + boolean isEnd = false; + HashMap children = new HashMap(); + // Initialize your data structure here. + public TrieNode() { + } + public TrieNode(char c) { + this.c = c; + } +} + +public class Trie { + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + // Inserts a word into the trie. + public void insert(String word) { + TrieNode node = root; + HashMap children = node.children; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!children.containsKey(c)) { + TrieNode newNode = new TrieNode(c); + children.put(c, newNode); + } + node = children.get(c); + children = node.children; + if (i == word.length() - 1) { + node.isEnd = true; + } + } + } + + // Returns if the word is in the trie. + public boolean search(String word) { + TrieNode node = root; + HashMap children = node.children; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!children.containsKey(c)) { + return false; + } else { + node = children.get(c); + children = node.children; + } + if (i == word.length() - 1) { + return node.isEnd; + } + } + return false; + } + + // Returns if there is any word in the trie + // that starts with the given prefix. + public boolean startsWith(String prefix) { + TrieNode node = root; + HashMap children = node.children; + for (char c : prefix.toCharArray()) { + if (!children.containsKey(c)) { + return false; + } else { + node = children.get(c); + children = node.children; + } + } + return true; + } + + +} + +// Your Trie object will be instantiated and called as such: +// Trie trie = new Trie(); +// trie.insert("somestring"); +// trie.search("key"); +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Implement strStr().java b/Others/old records/LeetCode-Merged/Java/Implement strStr().java new file mode 100644 index 0000000..4d95a0b --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Implement strStr().java @@ -0,0 +1,48 @@ +还挺多坑的. +1. border condition。 如果 haystack.length() < needle.length() 的话,必须错。但是这个可以优化省略。 +2. 当S2是“”的时候,也就是能在s1的其实位置找到s2....index = 0. +3. 记得如何在s1里面找s2. 就是把遍历s1的 i , 加上遍历s2的 j。 + +优化: +1. s1, s2长短可以不比较。因为forloop的时候: s1.length() - s2.length() + 1,如果s2长于s1,这里自然就断了。 +2. if(s1.charAT(i+j) == s2.charAT(j)). 可以省略。For loop 里面就Check到这个了。 +``` +/* +Implement strStr(). + +Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. + +Hide Company Tags Facebook +Hide Tags Two Pointers String +Hide Similar Problems (H) Shortest Palindrome + +*/ +public class Solution { + public int strStr(String haystack, String needle) { + if (needle == null || needle.length() == 0) { + return 0; + } + /* + else if (haystack == null || haystack.length() == 0 + || haystack.length() < needle.length()) { + return -1; + }*/ + int i = 0; + int j = 0; + + for (i = 0; i < haystack.length() - needle.length() + 1; i++) { + // if (haystack.charAt(i + j) == needle.charAt(j)) { + for (j = 0; j < needle.length(); j++) { + if (haystack.charAt(i + j) != needle.charAt(j)) { + break; + } + } + if (j == needle.length()) { + return i; + } + // } + } + return -1; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Insert Interval.java b/Others/old records/LeetCode-Merged/Java/Insert Interval.java new file mode 100644 index 0000000..1cdb29d --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Insert Interval.java @@ -0,0 +1,124 @@ +扫描线问题。 +Interval 拆点,PriorityQueue排点。 +Merge时用count==0作判断点。 + +PriorityQueue: O(logN). 扫n点,总共:O(nLogn) + +``` +/* +Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). + +You may assume that the intervals were initially sorted according to their start times. + +Example 1: +Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9]. + +Example 2: +Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16]. + +This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10]. + +Tags:Array, Sort +Similar Problems: (H) Merge Intervals + + +*/ + +/* +Thoughts: +What's the difference from merge intervals? +1. Create Class point (x, flag) +2. sort point in min-heap +3. when count increase and decreases to 0, that means we can close an interval +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ + +public class Solution { + + class Point { + int x; + int flag; + public Point(int x, int flag) { + this.x = x; + this.flag = flag; + } + } + public List insert(List intervals, Interval newInterval) { + List rst = new ArrayList(); + if (intervals == null && newInterval == null) { + return rst; + } else if (intervals == null) { + rst.add(newInterval); + return rst; + } else if (newInterval == null) { + return intervals; + } + + PriorityQueue queue = new PriorityQueue(1, new Comparator(){ + public int compare(Point a, Point b){ + return a.x - b.x; + } + }); + + for (Interval range: intervals) { + queue.add(new Point(range.start, 1)); + queue.add(new Point(range.end, -1)); + } + + queue.add(new Point(newInterval.start, 1)); + queue.add(new Point(newInterval.end, -1)); + + int count = 0; + int startNew = 0; + int endNew = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + if (count == 0) { + startNew = p.x; + } + count += p.flag; + + while (!queue.isEmpty() && p.x == queue.peek().x) { + p = queue.poll(); + count += p.flag; + } + + if (count == 0) { + endNew = p.x; + Interval addInterval = new Interval(startNew, endNew); + rst.add(addInterval); + } + + }//end while + + return rst; + + } +} + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Integer to English Words.java b/Others/old records/LeetCode-Merged/Java/Integer to English Words.java new file mode 100644 index 0000000..c6f8e58 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Integer to English Words.java @@ -0,0 +1,90 @@ +/* +Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 2^31 - 1. + +For example, +123 -> "One Hundred Twenty Three" +12345 -> "Twelve Thousand Three Hundred Forty Five" +1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" +Hint: + +Did you see a pattern in dividing the number into chunk of words? For example, 123 and 123000. +Group the number by thousands (3 digits). You can write a helper function that takes a number less than 1000 and convert just that chunk to words. +There are many edge cases. What are some good test cases? Does your code work with input such as 0? Or 1000010? (middle chunk is zero and should not be printed out) +Tags: Math, String +Similar Problems: (M) Integer to Roman + +Thoughts: +2^31 - 1 = 2,147,483,647 +Trillion, Billion, Million, Thousand, Hundred, Ninty .... Ten, Nine ... One, Zero. + +1. Break the words to up to 4 parts: new break[4] by /(1000 ^ i) +2. For each i, deal with that 3-digit number in break[i] +3. Append corresponding words for each break[i] + +Special case: +zero +000 in one break[i]: skip the whole thing +*/ + + +public class Solution { + public String[] v1 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; + public String[] v2 = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; + public String numberToWords(int num) { + if (num < 0) { + return ""; + } + if (num == 0) { + return "Zero"; + } + String rst = ""; + for (int i = 0; i < 4; i++) { + int partial = num - (num / 1000) * 1000; + if (partial > 0) { + rst = helper(partial, i) + " " + rst; + } + num /= 1000; + } + while (rst.charAt(rst.length() - 1) == ' ') { + rst = rst.substring(0, rst.length() - 1); + } + return rst; + } + + public String helper(int num, int i) { + String str = ""; + if (num >= 100) { + int hund = num / 100; + str = v1[hund] + " Hundred "; + num = num % 100; + } + + if (num < 20) { + str += v1[num] + " "; + } else { + int numTens = num / 10; + int numDigit = num % 10; + str += v2[numTens] + " "; + str += v1[numDigit] + " "; + } + + while (str.charAt(str.length() - 1) == ' ') { + str = str.substring(0, str.length() - 1); + } + + //depending on i: + switch (i) { + case 1 : + str += " Thousand"; + break; + case 2 : + str += " Million"; + break; + case 3 : + str += " Billion"; + break; + } + + return str; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Intersection of Two Linked Lists.java b/Others/old records/LeetCode-Merged/Java/Intersection of Two Linked Lists.java new file mode 100644 index 0000000..bbb28a9 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Intersection of Two Linked Lists.java @@ -0,0 +1,100 @@ +/* +Write a program to find the node at which the intersection of two singly linked lists begins. + + +For example, the following two linked lists: + +A: a1 → a2 + ↘ + c1 → c2 → c3 + ↗ +B: b1 → b2 → b3 +begin to intersect at node c1. + + +Notes: + +If the two linked lists have no intersection at all, return null. +The linked lists must retain their original structure after the function returns. +You may assume there are no cycles anywhere in the entire linked structure. +Your code should preferably run in O(n) time and use only O(1) memory. +Credits: +Special thanks to @stellari for adding this problem and creating all test cases. + +Tags: Linked List + +*/ +/* +Thgouts: +Check length of A,B +Start comparing from same distance from end. +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + if (headA == null && headB == null) { + return headA; + } + //Get size: + ListNode node = headA; + int sizeA = 0; + while(node != null) { + sizeA++; + node = node.next; + } + node = headB; + int sizeB = 0; + while(node != null) { + sizeB++; + node = node.next; + } + + ListNode nodeA = headA; + ListNode nodeB = headB; + int lenDiff = (sizeA >= sizeB ? 1 : -1) * (sizeA - sizeB); + node = sizeA >= sizeB ? headA : headB; + while (lenDiff > 0) { + node = node.next; + lenDiff--; + } + if (sizeA >= sizeB) { + nodeA = node; + } else { + nodeB = node; + } + while (nodeA != null) { + if (nodeA.val == nodeB.val) { + return nodeA; + } else { + nodeA = nodeA.next; + nodeB = nodeB.next; + } + }//END while + return null; + } +} + + + + + + + + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Jump Game.java b/Others/old records/LeetCode-Merged/Java/Jump Game.java new file mode 100644 index 0000000..b9df0a6 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Jump Game.java @@ -0,0 +1,38 @@ +LintCode做过。 +用一个farest can go 来做个一个点的DP,记录可以跑到得最远的地方。 +``` +/* +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Determine if you are able to reach the last index. + +For example: +A = [2,3,1,1,4], return true. + +A = [3,2,1,0,4], return false. + +Hide Tags Array Greedy + +*/ + +public class Solution { + public boolean canJump(int[] nums) { + if (nums == null || nums.length <= 1) { + return true; + } + int farest = 0; + for (int i = 0; i < nums.length; i++) { + farest = Math.max(farest, nums[i] + i); + if (farest >= nums.length - 1) { + return true; + } + if (farest <= i) { + return false; + } + } + return true; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Kth Smallest Element in a BST.java b/Others/old records/LeetCode-Merged/Java/Kth Smallest Element in a BST.java new file mode 100644 index 0000000..2b70b2a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Kth Smallest Element in a BST.java @@ -0,0 +1,127 @@ +很容想到Inorder-binary-search-tree Traversal +Recursive 不难,然后稍微优化一下,确保rst.size() == k 时候,就可以return了。 +Iterative 稍微难想点:先把最左边的add, pop() stack, 加上右边(如果存在); 下一个轮回,如果又左孩子,又是一顿加。 + +``` +/* +Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. + +Note: +You may assume k is always valid, 1 ≤ k ≤ BST's total elements. + +Follow up: +What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? + +Hint: + +Try to utilize the property of a BST. +What if you could modify the BST node's structure? +The optimal runtime complexity is O(height of BST). +Credits: +Special thanks to @ts for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Tree Binary Search +Hide Similar Problems (M) Binary Tree Inorder Traversal + +*/ + +/* + + Based on binary seach tree, just do a in-order-traversal. + Store in rst. +*/ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ + + +/* + //Iterative + + Add all left. + pop top (which will be left-most node) + set node = node.right; + if right != null, add to stack. Will trigger the left-adding-while-loop + if right == null, now node = null. Will not trigger the left-adding-whilte-loop +*/ +public class Solution { + public int kthSmallest(TreeNode root, int k) { + if (root == null || k <= 0) { + return -1; + } + + Stack stack = new Stack(); + stack.push(root); + TreeNode node = root; + while(!stack.isEmpty()) { + //Left first + while (node != null && node.left != null) { + stack.add(node.left); + node = node.left; + } + //Process left/curr + node = stack.pop(); + k--; + if (k == 0) { + return node.val; + } + node = node.right; + if (node != null) { + stack.push(node); + } + } + + return -1; + } + +} + + + +// Recursive +public class Solution { + public int kthSmallest(TreeNode root, int k) { + if (root == null || k <= 0) { + return -1; + } + + ArrayList rst = new ArrayList(); + helper(rst, root, k); + + if (rst.size() < k) { + return -1; + } + return rst.get(k - 1).val; + } + + + public void helper(ArrayList rst, TreeNode node, int k) { + if (rst.size() == k) { + return; + } + if (node.left == null && node.right == null) { + rst.add(node); + return; + } + + if (node.left != null) { + helper(rst, node.left, k); + } + rst.add(node); + if (node.right != null) { + helper(rst, node.right, k); + } + } +} + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/LRU Cache.java b/Others/old records/LeetCode-Merged/Java/LRU Cache.java new file mode 100644 index 0000000..3a20665 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/LRU Cache.java @@ -0,0 +1,170 @@ +当李特第一次把这题拿出来的时候,我是慌的。 +啥是LRU Cache啊? 接下去看吧。 + +后来,我很天真的来了一个O(n) 的解法,结果果然时间过多。 +天真解法很简单啊:一个map存数值。一个queue来存排位。 +每次有更新,就把最新的放在末尾;每次超过capaticity,就把大头干掉。很简单嘛,但是跑起来太久,失败了。 + +于是就来了第二个做法。其实还是跟方法一是类似的。只不过用了一个特别的双向的LinkNode,有了head和tail,这样就大大加快了速度。 +主要加快的就是那个‘更新排位’的过程,过去我是O(n),现在O(1)就好了。具体看下面。 + +巧妙点: +1. head和tail特别巧妙:除掉头和尾,和加上头和尾,就都特别快。 +2. 用双向的pointer: pre和next, 当需要除掉任何一个node的时候,只要知道要除掉哪一个, +直接把node.pre和node.next耐心连起来就好了,node就自然而然的断开不要了。 + +李特的这个Design的题目很有意思。果然值得被作为Hard。但是一旦知道怎么解决了,就不是很特别,因为并不是难想的算法。 + +```` +/* +Design and implement a data structure for Least Recently Used (LRU) cache. +It should support the following operations: get and set. + +get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. +set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. + +Tags: Design + +*/ +/* +It looks like we need to do some design, according to (http://www.cnblogs.com/yuzhangcmu/p/4113462.html). Though, the solution's concept is quite similar as attempt1. + +1. The design uses HashMap, and 2-way LinkedList. Map +2. Use two dummy node: head and tail. When add/remove nodes, we are add/remove nodes in between head and tail. + So. head.next is our real 1st element + andd tail.pre is our real last element + +Note: +Be careful: when removing a node due to capacity issue, remember to remove both 1st node(head.next) and the corresponding entry in the map: map.remove(head.next.key) +*/ +public class LRUCache { + private class LinkNode { + int key; + int val; + LinkNode pre = null; + LinkNode next = null; + LinkNode(int key, int val) { + this.key = key; + this.val = val; + } + } + + private int cap; + private HashMap map; + private LinkNode head; + private LinkNode tail; + public LRUCache(int capacity) { + this.cap = capacity; + this.map = new HashMap(); + this.head = new LinkNode(-1, -1); + this.tail = new LinkNode(-1, -1); + head.next = tail; + tail.pre = head; + } + + public int get(int key) { + if (map.containsKey(key)) { + LinkNode temp = map.get(key); + moveUsedToTail(temp); + return temp.val; + } else { + return -1; + } + } + + public void set(int key, int value) { + if (map.containsKey(key)) { + LinkNode temp = map.get(key); + temp.val = value; + moveUsedToTail(temp); + } else { + if (map.size() >= cap) { + map.remove(head.next.key); + removeHead(); + } + LinkNode newNode = new LinkNode(key, value); + addTail(newNode); + map.put(key, newNode); + } + } + + public void moveUsedToTail(LinkNode node) { + removeNode(node); + addTail(node); + } + + public void removeHead(){//O(1) + removeNode(head.next); + } + public void addTail(LinkNode node){//O(1) + tail.pre.next = node; + node.pre = tail.pre; + node.next = tail; + tail.pre = node; + } + public void removeNode(LinkNode node) {//O(1) + node.pre.next = node.next; + node.next.pre = node.pre; + } +} + +```` +```` +/* +First Attempt: time exceeds + +Thoughts: +Easy to implement: cache the least-added item. However, we are looking for the cache of 'leaset-recently-used item'. + +'used' means the get() method: +whenever get, remove that key from the queue, and move that key to top. + +Time Cost: O(n) on get(), set() + + +*/ + +public class LRUCache { + private int cap; + private HashMap map; + private LinkedList queue; + public LRUCache(int capacity) { + this.cap = capacity; + this.map = new HashMap(); + this.queue = new LinkedList(); + } + + public int get(int key) { + if (map.containsKey(key)) { + moveUsedToTop(key); + return map.get(key); + } else { + return -1; + } + } + + public void set(int key, int value) { + if (map.containsKey(key)) { + moveUsedToTop(key); + map.put(key, value); + } else { + if (queue.size() >= cap) { + map.remove(queue.poll()); + } + queue.offer(key); + map.put(key, value); + } + + } + //O(n) + public void moveUsedToTop(int key) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i) == key) { + queue.remove(i); + queue.offer(key); + break; + } + } + } +} +```` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Letter Combinations of a Phone Number.java b/Others/old records/LeetCode-Merged/Java/Letter Combinations of a Phone Number.java new file mode 100644 index 0000000..fa31b0c --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Letter Combinations of a Phone Number.java @@ -0,0 +1,176 @@ +/* +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"]. +Note: +Although the above answer is in lexicographical order, your answer could be in any order you want. + +Hide Company Tags Uber Facebook +Hide Tags Backtracking String +Hide Similar Problems (M) Generate Parentheses (M) Combination Sum +*/ + +/* + Thoughts: + basic: use 2 queue. one queue as base. the other is result. swap the base and result when based is all poll() out. +*/ +//Use 2 queues +public class Solution { + public List letterCombinations(String digits) { + List rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + HashMap map = new HashMap(); + map.put(2, "abc");map.put(3, "def"); + map.put(4, "ghi");map.put(5, "jkl");map.put(6, "mno"); + map.put(7, "pqrs");map.put(8,"tuv");map.put(9,"wxyz"); + + Queue base = new LinkedList(); + Queue queue = new LinkedList(); + + //init + int index = 0; + int digit = Integer.parseInt(digits.substring(index, index + 1)); + char[] arr = map.get(digit).toCharArray(); + index++; + + for (char c : arr) { + base.offer(c+""); + } + if (index == digits.length()) { + queue = base; + } + + while (index < digits.length() && !base.isEmpty()) { + String str = base.poll(); + digit = Integer.parseInt(digits.substring(index, index + 1)); + arr = map.get(digit).toCharArray(); + for (char key : arr) { + queue.offer(str + key); + } + + if (base.isEmpty() && index < digits.length() - 1) { + Queue temp = base; + base = queue; + queue = temp; + index++; + } + }//end while + + while (!queue.isEmpty()) { + rst.add(queue.poll()); + } + + return rst; + } +} + + +//Use 1 queue +// and optimize a bit +public class Solution { + public List letterCombinations(String digits) { + List rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + HashMap map = new HashMap(); + map.put(2, "abc");map.put(3, "def"); + map.put(4, "ghi");map.put(5, "jkl");map.put(6, "mno"); + map.put(7, "pqrs");map.put(8,"tuv");map.put(9,"wxyz"); + + Queue queue = new LinkedList(); + + //init + int index = 0; + int digit = Integer.parseInt(digits.substring(index, index + 1)); + String keys = map.get(digit); + index++; + + for (int i = 0; i < keys.length(); i++) { + queue.offer(keys.substring(i,i+1)); + } + int size = queue.size(); + + while (index < digits.length() && !queue.isEmpty()) { + String str = queue.poll(); + digit = Integer.parseInt(digits.substring(index, index + 1)); + keys = map.get(digit); + for (int i = 0; i < keys.length(); i++) { + queue.offer(str + keys.substring(i,i+1)); + } + size--; + if (size == 0 && index < digits.length() - 1) { + index++; + size = queue.size(); + } + }//end while + + while (!queue.isEmpty()) { + rst.add(queue.poll()); + } + + return rst; + } +} + + + + + +public class Solution { + /** + * @param digits A digital string + * @return all posible letter combinations + */ + public ArrayList letterCombinations(String digits) { + ArrayList rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + ArrayList map = new ArrayList(); + map.add(new String[]{});//key 0: nothing + map.add(new String[]{});//key 1: nothing + map.add(new String[]{"a","b","c"}); + map.add(new String[]{"d","e","f"}); + map.add(new String[]{"g","h","i"}); + map.add(new String[]{"j","k","l"}); + map.add(new String[]{"m","n","o"}); + map.add(new String[]{"p","q","r","s"}); + map.add(new String[]{"t","u","v"}); + map.add(new String[]{"w","x","y","z"}); + + ArrayList list = new ArrayList(); + helper(rst, list, map, digits, 0); + + return rst; + } + + public void helper(ArrayList rst, ArrayList list, + ArrayList map, String digits, int level){ + //If level is finished, compress into string + if (level == digits.length()) { + StringBuffer sb = new StringBuffer(); + for (String s : list) { + sb.append(s); + } + rst.add(sb.toString()); + return; + } + //For a specific list of candidates, face the level of chars + int num = Integer.parseInt(digits.substring(level, level + 1)); + String[] strs = map.get(num); + + for (int i = 0; i < strs.length; i++) { + list.add(strs[i]); + helper(rst, list, map, digits, level + 1); + list.remove(list.size() - 1); + } + } + +} + diff --git a/Others/old records/LeetCode-Merged/Java/Longest Palindromic Substring.java b/Others/old records/LeetCode-Merged/Java/Longest Palindromic Substring.java new file mode 100644 index 0000000..031ad99 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Longest Palindromic Substring.java @@ -0,0 +1,114 @@ +这个琢磨了我好半天。 +第一个方法至少O(n^3),果然时间太多,输了给了李特。这种方法从两头check (i,j),太慢。 + +第二个方法,是Code Granker上面的,利用了高中学排列组合时候的概念。 +有个‘abc’,那么总共可以看成'a_b_c' 5个字符位置。 +分为两种情况: 一种是在'a|b'的间隙里面分割;一种是'abc'分割在'b'上。这样是O(2n-1)*O(n) = O(n^2),还不错。 + +方法三应该是DP。还没有细细研究。 + +```` +/* +Given a string S, find the longest palindromic substring in S. +You may assume that the maximum length of S is 1000, +and there exists one unique longest palindromic substring. + +Tags: String +Similar Problems: (H) Shortest Palindrome, (E) Palindrome Permutation + +*/ + +/* +Attempt2: http://blog.csdn.net/linhuanmars/article/details/20888595, Code Granker + +Assuming index x is the middle of the longest palindromic substring. Start from the middle, and check left,right indexes see if that are matching. + +How many different index x can we check? +Think of string "abcd" as "a b c d", where the x can be any of 'a,b,c,d' character, and it can also just be in between of any two characters. That makes the total number of x to check: 2*n - 1. (n chars, and n-1 in-between space) + +More details: + When x is odd: x % 2 == 1, it's this pattern: a_b_c_d, for example x/2 = i lands on the 2nd space ' ', i == 3. + So: left = x/2 = 3 = ' '; right = x/2 = 3 = ' '. Right now, we are almost going to compare 'a_b' and '_c_d'.However, right needs to +1, because the we really want to compare 'a_b' and 'c_d'. We are split by the in-between-space, good to go. + + When x is even: x % 2 = 0, it's a_b_c, for example i lands on 'b', i ==2. + So:left = x/2 = 2 = 'b'; right = x/2 = 2 = 'b'; We are splitting the string on 'b', it's okay. Then just split them like: 'a_' and '_c'. + + In conclusion: when x % 2 == 1: right = x/2 + 1; + +Also, for each 'left' and 'right', start expanding left-- and right-- as long as they match the pattern of palindromic. Whenever failed to match, return whatever length of palindromic substring. +Track the max length and max string. +*/ + +public class Solution { + public String longestPalindrome(String s) { + if (s == null || s.length() <= 1) { + return s; + } + int x = 2 * s.length() - 1; + String str = ""; + int max = 0; + for (int i = 0; i < x; i++) {//Check through the 2*len - 1 + int left = i / 2; + int right = i / 2; + if (i % 2 == 1) { + right++; + } + //Check Palindromic + while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { + left--; + right++; + } + String temp = s.substring(left + 1, right); + //Track max + if (temp.length() > max) { + max = temp.length(); + str = temp; + } + }//END for + return str; + } +} + +/* +1st Attempt.Thoughts: +Check palindromic with while(start < end){}. +Double-for loop on i ~ n. +Time: O(n^2 * n/2) = O(n^3) +*/ +public class Solution { + public String longestPalindrome(String s) { + if (s == null || s.length() <= 1) { + return s; + } + String rst = ""; + for (int i = 0; i < s.length(); i++) { + for (int j = s.length() - 1; j > i; j--) { + int start = i; + int end = j; + String str = s.substring(i,j + 1); + boolean isPalindromic = true; + while (start < end && isPalindromic) { + if (s.charAt(start) != s.charAt(end)) { + isPalindromic = false; + } else { + start++; + end--; + } + } + if (isPalindromic) { + if (str.length() > rst.length()) { + rst = str; + } + } + } + }//END for + return rst; + } +} + + + + + + +```` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Lowest Common Ancestor of a Binary Search Tree.java b/Others/old records/LeetCode-Merged/Java/Lowest Common Ancestor of a Binary Search Tree.java new file mode 100644 index 0000000..99577cf --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Lowest Common Ancestor of a Binary Search Tree.java @@ -0,0 +1,74 @@ +/* +Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. + +According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).” + + _______6______ + / \ + ___2__ ___8__ + / \ / \ + 0 _4 7 9 + / \ + 3 5 +For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition. + +Tags: Tree +Similar Problems: (M) Lowest Common Ancestor of a Binary Tree + +*/ +/* +Thoughts: +Create 2 path: l1, l2. +First different node's parent, will be the LCA +Do binary search to generate the path l1,l2 + +Note: +When one of the target is root, make sure parent = root, and return root at the end. This is because: the if statement (l1.get(i).val != l2.get(i).val) won't capture this case; instead, the for loop ends by i == size. So, be careful here. +*/ + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || p == null || q == null) { + return null; + } + ArrayList l1 = new ArrayList(); + ArrayList l2 = new ArrayList(); + binarySearch(root, p, l1); + binarySearch(root, q, l2); + + TreeNode parent = root; + int size = l1.size() > l2.size() ? l2.size() : l1.size(); + for (int i = 0; i < size; i++) { + if (l1.get(i).val == l2.get(i).val) { + parent = l1.get(i); + } else { + return parent; + } + } + return parent; + } + + + public void binarySearch(TreeNode root, TreeNode target, ArrayList list) { + TreeNode node = root; + while (node != null) { + list.add(node); + if (node.val == target.val) { + return; + } else if (node.val < target.val) { + node = node.right; + } else { + node = node.left; + } + }//END while + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/MaximumSubarray.java b/Others/old records/LeetCode-Merged/Java/MaximumSubarray.java new file mode 100644 index 0000000..b5f0b27 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/MaximumSubarray.java @@ -0,0 +1,36 @@ +/* +Find the contiguous subarray within an array (containing at least one number) which has the largest sum. + +For example, given the array [−2,1,−3,4,−1,2,1,−5,4], +the contiguous subarray [4,−1,2,1] has the largest sum = 6. + +click to show more practice. + +More practice: +If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. + +Hide Tags Divide and Conquer Array Dynamic Programming + +Thinking process: +1. DP: store calculated sum for comparison use: compare with max to get true max value. +2. Max sum from previous index to current: + at index i, try to compare if pre + current > current index value. If yes, use pre + current; if NO, just use current as max. + Compare max with Sum[i] for final max vlaualuealuee. + +*/ + +public class Solution { + public int maxSubArray(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int[] sum = new int[A.length]; + sum[0] = A[0]; + int max = sum[0]; + for (int i = 1; i < sum.length; i++) { + sum[i] = Math.max(A[i], sum[i - 1] + A[i]); + max = Math.max(max, sum[i]); + } + return max; + } +} diff --git a/Others/old records/LeetCode-Merged/Java/Median of Two Sorted Arrays.java b/Others/old records/LeetCode-Merged/Java/Median of Two Sorted Arrays.java new file mode 100644 index 0000000..a534488 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Median of Two Sorted Arrays.java @@ -0,0 +1,35 @@ +/* +There are two sorted arrays nums1 and nums2 of size m and n respectively. +Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). +*/ + + +/* +THoughts: +max-heap on left and min-heap on right; Center: the median +left heap size: x +right heap size: x, or x + 1 + +However, this might (m+n)Log(m+n) + +*/ + +//NOT DONE +public class Solution { + public double findMedianSortedArrays(int[] nums1, int[] nums2) { + if (nums1 == null && nums2 == null) { + return 0; + } + //min-heap + PriorityQueue minHeap = new PriorityQueue(); + PriorityQueue maxHeap = new PriorityQueue(1, new Comparator(){ + public int compare(int x, int y){ + return y - x; + } + }); + + int median = Integer.MIN_VALUE; + + + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Meeting Rooms II.java b/Others/old records/LeetCode-Merged/Java/Meeting Rooms II.java new file mode 100644 index 0000000..586fd8a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Meeting Rooms II.java @@ -0,0 +1,116 @@ +开会王,还是可以用PriorityQueue + 一个Class来解决。 +这里有尝试了一下用一个sorted Array + HashMap: 也还行,但是handle edge的时候,HashMap 要小心,因为相同时间start和end的map key 就会重复了。 + +``` +/* +Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required. + +For example +Given [[0, 30],[5, 10],[15, 20]], +return 2. + +Tags: Heap Greedy Sort +Similar Problems: (H) Merge Intervals, (E) Meeting Rooms +*/ + +/* +Thoughts: This seems to be: how many concurrent meetings do we have? +Just return the count that we used in Meeting I. + +Though, instead of Prority queue + Point class, let me try to use just array and a hashmap. + +Using HashMap is tricky in this: +Overallpping spot will be put on the same hashmap key. Be careful with handling the overlapping. +Here, I decide to merge the edge when generate the map, so during the count check, need to skip +duplicated time spot to prevent incorrectly re-use of certain time spot. + + +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ +public class Solution { + public int minMeetingRooms(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return 0; + } + int[] timeSpot = new int[intervals.length * 2]; + HashMap map = new HashMap(); + for (int i = 0; i < intervals.length; i++) { + timeSpot[i] = intervals[i].start; + timeSpot[intervals.length + i] = intervals[i].end; + if (map.containsKey(intervals[i].start)) { + map.put(intervals[i].start, map.get(intervals[i].start) + 1); + } else { + map.put(intervals[i].start, 1); + } + if (map.containsKey(intervals[i].end)) { + map.put(intervals[i].end, map.get(intervals[i].end) - 1); + } else { + map.put(intervals[i].end, -1); + } + } + Arrays.sort(timeSpot); + int count = 0; + int max = 0; + for (int i = 0; i < timeSpot.length; i++) { + count += map.get(timeSpot[i]); + while (i + 1 < timeSpot.length && timeSpot[i] == timeSpot[i + 1]) { + i++; + } + max = Math.max(count, max); + } + return max; + } +} + + +// Similar to Meeting Room I, using Point class and Priorityqueue +// Creating a customized class, but makes the problem a bit easier to think. + +public class Solution { + class Point { + int pos; + int flag; + public Point(int pos, int flag) { + this.pos = pos; + this.flag = flag; + } + } + public int minMeetingRooms(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return true; + } + PriorityQueue queue = new PriorityQueue( + new Comparator(){ + public int compare(Point a, Point b){ + return (a.pos - b.pos); + } + } + ); + for (Interval range : intervals) { + queue.add(new Point(range.start, 1)); + queue.add(new Point(range.end, -1)); + } + int count = 0; + int max = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count += p.flag; + while(!queue.isEmpty() && p.pos == queue.peek().pos) { + p = queue.poll(); + count += p.flag; + } + max = Math.max(max, count); + } + return max; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Meeting Rooms.java b/Others/old records/LeetCode-Merged/Java/Meeting Rooms.java new file mode 100644 index 0000000..5fc790f --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Meeting Rooms.java @@ -0,0 +1,68 @@ +扫描线是个好厨师。 +注意接头点要考虑所有开会结会的情况,不要恰巧漏掉相接的点。 +这开会的dude是个超人。瞬间移动接上下一个会议。 +``` +/* +Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings. + +For example, +Given [[0, 30],[5, 10],[15, 20]], +return false. +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ + +/* +Thought: +Use scane line. +Note: special care for edge point: make sure to process all connecting point before shuouting the result. +*/ + + public class Solution { + class Point { + int pos; + int flag; + public Point(int pos, int flag) { + this.pos = pos; + this.flag = flag; + } + } + public boolean canAttendMeetings(Interval[] intervals) { + if (intervals == null || intervals.length == 0) { + return true; + } + PriorityQueue queue = new PriorityQueue( + new Comparator(){ + public int compare(Point a, Point b){ + return (a.pos - b.pos); + } + } + ); + for (Interval range : intervals) { + queue.add(new Point(range.start, 1)); + queue.add(new Point(range.end, -1)); + } + int count = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count += p.flag; + while(!queue.isEmpty() && p.pos == queue.peek().pos) { + p = queue.poll(); + count += p.flag; + } + if (count > 1) { + return false; + } + } + return true; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Merge Intervals.java b/Others/old records/LeetCode-Merged/Java/Merge Intervals.java new file mode 100644 index 0000000..09eb0ba --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Merge Intervals.java @@ -0,0 +1,156 @@ +扫描线+Count无敌手。注意start end把interval给合起来。 +count==0的时候,就是每次start end双数抵消的时候,就应该是一个interval的开头/结尾。写个例子就知道了。 + +空间:O(2n) -> O(n) +时间,priorityqueue: O(nlogn) + +记得怎么写comparator + + + +或者O(n) +Collections.sort() on interval.start之后,试着跑一遍,按照merge的需求,把需要merge的地方续好,然后减掉多余的interval就好。 +Basic implementation +/* + new Comparator(){ + public int compare(obj1, obj2) { + return obj1.x - obj2.x; + } + + } +*/ + +``` +/* +Given a collection of intervals, merge all overlapping intervals. + +For example, +Given [1,3],[2,6],[8,10],[15,18], +return [1,6],[8,10],[15,18]. + +Tags: Array, Sort +Similar Problems: (H) Insert Interval, (E) Meeting Rooms (M) Meeting Rooms II + +*/ + +/* + Thoughts: 12.09.2015 + Recap. Use O(1) + + Sort by start time. + then it overlaps: check on pre.end and curr.start. + if overlaps: curr.start will be overlapped; also check on curr.end and pre.end, decide who ends this interval + + border case: null, return itself; or length==1, return. +*/ + +class Solution { + /** + * @param intervals: Sorted interval list. + * @return: A new sorted interval list. + */ + public List merge(List intervals) { + if (intervals == null || intervals.size() <= 1) { + return intervals; + } + + Collections.sort(intervals, new Comparator(){ + public int compare(Interval a, Interval b) { + return a.start - b.start; + } + }); + Interval prev = intervals.get(0); + Interval curr; + + for (int i = 1; i < intervals.size(); i++) { + curr = intervals.get(i); + if (prev.end >= curr.start) { + if (prev.end <= curr.end) { + prev.end = curr.end; + } + intervals.remove(i); + i--; + } else { + prev = curr; + } + } + + return intervals; + } + +} + +/* +Thoughts: +Again use scan line. Quite similar to Meeting Rooms, flight schedules... etc +This one: when count ==0, make sure to keep track start and end, add into the rst +When writing out example, whenever count==0, that indicates an end of a interval. + +HOWEVER, this uses O(n) space, while this problem requests O(1) space +*/ + +/** + * Definition for an interval. + * public class Interval { + * int start; + * int end; + * Interval() { start = 0; end = 0; } + * Interval(int s, int e) { start = s; end = e; } + * } + */ +public class Solution { + class Point { + int pos; + int flag; + public Point(int pos, int flag) { + this.pos = pos; + this.flag = flag; + } + } + + public List merge(List intervals) { + List rst = new ArrayList(); + if (intervals == null || intervals.size() == 0) { + return rst; + } + PriorityQueue queue = new PriorityQueue( + new Comparator(){ + public int compare(Point a, Point b){ + return (a.pos - b.pos); + } + } + ); + for (Interval range : intervals) { + queue.add(new Point(range.start, 1)); + queue.add(new Point(range.end, -1)); + } + int count = 0; + int start = 0; + int end = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + if (count == 0) { + start = p.pos; + } + count += p.flag; + while(!queue.isEmpty() && p.pos == queue.peek().pos) { + p = queue.poll(); + count += p.flag; + } + if (count == 0) { + end = p.pos; + rst.add(new Interval(start, end)); + } + } + return rst; + } +} + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Merge Two Sorted Lists.java b/Others/old records/LeetCode-Merged/Java/Merge Two Sorted Lists.java new file mode 100644 index 0000000..e31e208 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Merge Two Sorted Lists.java @@ -0,0 +1,50 @@ +/* +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. + +Tags: Linked List +Similar Problems: (H) Merge k Sorted Lists, (E) Merge Sorted Array, (M) Sort List, (M) Shortest Word Distance II + +*/ + +/* +Thouhts: +Loop throgh both list. Make sure to check the border cases +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } + ListNode node = new ListNode(0); + ListNode dummy = node; + while (l1 != null || l2 != null) { + if (l1 == null) { + node.next = l2; + break; + } else if (l2 == null) { + node.next = l1; + break; + } else { + if (l1.val < l2.val) { + node.next = l1; + l1 = l1.next; + } else { + node.next = l2; + l2 = l2.next; + } + node = node.next; + } + }//end while + return dummy.next; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Merge k Sorted Lists.java b/Others/old records/LeetCode-Merged/Java/Merge k Sorted Lists.java new file mode 100644 index 0000000..29e11cd --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Merge k Sorted Lists.java @@ -0,0 +1,72 @@ +事情是这样的。今天李特除了一题,据说是Hard。 +我一看好像曾经见过,于是做了做,时间复杂度最后大约是O(kn)*O(logn). 因为用到了PriorityQueue, 里面的offer() 和 poll()都是O(logn)的时间。 + +总而言之就是: +先把每个ListNode放进queue。 +然后逐个击破。每次击破,都要把小孩扔进queue。 + +这里有复习了一下 +```` +new Comparator<...>{}的用法 + +PriorityQueue queue = new PriorityQueue(new Comparator(){ + public compare(xx A, xx B) { + return A.value - B.value;//只要A queue = new PriorityQueue(new Comparator(){ + public int compare(ListNode a, ListNode b){ + return a.val - b.val; + } + }); + //Populate queue with initial node with correct ordering + for (int i = 0; i < lists.length; i++) { + if(lists[i] != null) { + queue.offer(lists[i]); + } + } + + //add to rst + while (!queue.isEmpty()) { + ListNode temp = queue.poll(); + node.next = temp; + if (temp.next != null) { + queue.offer(temp.next); + } + node = node.next; + } + return dummy.next; + } +} +```` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Min Stack.java b/Others/old records/LeetCode-Merged/Java/Min Stack.java new file mode 100644 index 0000000..63dfa9d --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Min Stack.java @@ -0,0 +1,52 @@ +双Stack. 小心stack.peek() 而不是 pop +``` +/* +Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. + +push(x) -- Push element x onto stack. +pop() -- Removes the element on top of the stack. +top() -- Get the top element. +getMin() -- Retrieve the minimum element in the stack. + +Tags: Stack, Design +Similar Problems: (H) Sliding Window Maximum + + +Thoughts: +Use a regular Stack: linked list. +Save that minimum integer in a HashMap with each stack value. At each level of the stack, it always stores the min till that moment. +Use another stack to hold that 'up-to-date' min values. + +Note: +Stack: peek() + +*/ + +class MinStack { + Stack stack = new Stack(); + Stack min = new Stack(); + public void push(int x) { + stack.push(x); + if (min.isEmpty() || x < min.peek()){ + min.push(x); + } else { + min.push(min.peek()); + } + } + + public void pop() { + stack.pop(); + min.pop(); + } + + public int top() { + return stack.peek(); + } + + public int getMin() { + return min.peek(); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Minimum Height Trees.java b/Others/old records/LeetCode-Merged/Java/Minimum Height Trees.java new file mode 100644 index 0000000..c1f3e10 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Minimum Height Trees.java @@ -0,0 +1,121 @@ +/* +For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. + +Format +The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). + +You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + +Example 1: + +Given n = 4, edges = [[1, 0], [1, 2], [1, 3]] + + 0 + | + 1 + / \ + 2 3 +return [1] + +Example 2: + +Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] + + 0 1 2 + \ | / + 3 + | + 4 + | + 5 +return [3, 4] + +Show Hint +Note: + +(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.” + +(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf. + +Credits: +Special thanks to @peisi for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Breadth-first Search Graph +Hide Similar Problems (M) Course Schedule (M) Course Schedule II + +*/ + + +/* + Starting from leaf with depth == 1, + remove all leaf, and the edge + Till the end, whatever node left, should be the root. + + * WHen there is only 1,2 nodes remaining. that's the rst. + + Put Node in HahsMap + + Iterative over map till map.size() <= 2 + + border n == 2,1, just returl rst. + edges == null, return null. + edges.length == 1, reutrn list +*/ + +public class Solution { + public List findMinHeightTrees(int n, int[][] edges) { + List rst = new ArrayList(); + if (n == 1) { + rst.add(0); + return rst; + }else if (n == 0 || edges == null || edges.length == 0 || edges.length != n - 1) { + return rst; + } + + //populate map + boolean[] nodes = new boolean[n]; + HashMap> map = new HashMap>(); + for (int i = 0; i < n; i++) { + map.put(i, new ArrayList()); + nodes[i] = true; + } + for (int i = 0; i < edges.length; i++) { + if (!map.get(edges[i][0]).contains(edges[i][1])) { + map.get(edges[i][0]).add(edges[i][1]); + } + if (!map.get(edges[i][1]).contains(edges[i][0])) { + map.get(edges[i][1]).add(edges[i][0]); + } + } + + //Remove list with leng == 1 + Queue queue = new LinkedList(); + while (n > 2) { + for (Map.Entry> entry : map.entrySet()) { + if (entry.getValue().size() == 1) { + queue.offer(entry.getKey()); + } + } + while (!queue.isEmpty()) { + n--; + Integer key = queue.poll(); + nodes[key] = false; + int from = map.get(key).get(0); + map.get(from).remove(key); + map.get(key).remove(0); + + } + } + + //Put remaining into rst + for (int i = 0; i < nodes.length; i++) { + if (nodes[i]) { + rst.add(i); + } + + } + + return rst; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Missing Ranges.java b/Others/old records/LeetCode-Merged/Java/Missing Ranges.java new file mode 100644 index 0000000..c0620b6 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Missing Ranges.java @@ -0,0 +1,69 @@ +精力旺盛症。 +自己做的时候,想的太复杂,做起了binarysearch,企图节省时间。 +下次要算清楚,是否有意义。 +binarySearch的确logn,但是在lower 和upper之间的数字,很可能还是O(n). +因此一开始就for一遍也是O(n), 而code会相对来说简单许多。 + +想法: +两个pointer, 每次计较prev和curr之间的部分。 +然后prev = curr,向前移动一格。 + +``` +/* +Given a sorted integer array where the range of elements are [lower, upper] inclusive, return its missing ranges. + +For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. + +Tags: Array +Similar Problems: (E) Summary Ranges + + +*/ +/* + +Attempt2, Thoughts: +Use two pointer to mark the prev and curr value, then verify the range in between. + +matching conditoin: prev +2 >= curr. +That is, +1,...,3 + +1. When print range: print the missing [x,y] +2. missing x = prev+1, missing y = curr - 1; +3. Make sure prev represents the consecutive integer before missing x. +*/ + +public class Solution { + public List findMissingRanges(int[] nums, int lower, int upper) { + List rst = new ArrayList(); + if (nums == null || nums.length == 0) {//Though, also covered in the for + rst.add(printRange(lower, upper)); + return rst; + } else if (lower > upper) { + return rst; + } + int prev = lower - 1; + int curr; + for (int i = 0; i <= nums.length; i++) { + curr = (i == nums.length) ? upper + 1 : nums[i]; + if (prev + 2 <= curr) { + rst.add(printRange(prev + 1, curr - 1)); + } + prev = curr; + } + return rst; + } + + public String printRange(int from, int to) { + return (from == to) ? String.valueOf(from) : from + "->" + to; + } +} + + +/* +Old solution: attempted to do binary search for lower and upper, then calculate the mid range. O(logn) + O(upper - lower) = O(n) + +Therefore, don't have to do that; just do a run through. + +*/ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Multiply Strings.java b/Others/old records/LeetCode-Merged/Java/Multiply Strings.java new file mode 100644 index 0000000..2237ef4 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Multiply Strings.java @@ -0,0 +1,98 @@ +想法不难。turn into int[], 然后每个位子乘积,然后余数carrier移位。 + +但是做起来有很多坑。适合面试黑。 + +1. 数字‘123’, 在数组里面, index == 0 是 ‘1’。 但是我们平时习惯从最小位数开始乘积,就是末尾的'3'开始。 + 所以!翻转两个数字先!我去。这个是个大坑。 + +2. 乘积product,和移动Carrier都很普通。 + +3. !!最后不能忘了再翻转。 + +4. 最后一个看坑。要是乘积是0,就返回‘0’。 但是这个其实可以在开头catch到没必要做到结尾catch。 + +用到几个StringBuffer的好东西: +reverse(); +sb.deleteCharAt(i) + +//找数字,或者26个字母,都可以: +s.charAt(i) - '0'; //数字 +s.charAt(i) - 'a'; //字母 + +``` +/* +Given two numbers represented as strings, return multiplication of the numbers as a string. + +Note: The numbers can be arbitrarily large and are non-negative. + +Hide Company Tags Facebook +Hide Tags Math String +Hide Similar Problems (M) Add Two Numbers (E) Plus One (E) Add Binary + +*/ +/* + Thoughts: + 1. too long to multiply int. so convert to int[] + 2. Multiply by definition: + a. create a product[] of num1.size() + num2.size() - 1 + b. catches each product[i + j] + 3. for loop on product array again, to carry over the carries + + if both null, return null. + if both "", return "" + + O(m + n) +*/ +public class Solution { + public String multiply(String num1, String num2) { + if (num1 == null || num2 == null) { + return ""; + } else if (num1.length() == 0 || num2.length() == 0) { + return num1.length() == 0 ? num2 : num1; + } else if (num1.equals("0") || num2.equals("0")) { + return "0"; + } + //reverse string, so to calculate from 0 base. easier to calculate + num1 = new StringBuffer(num1).reverse().toString(); + num2 = new StringBuffer(num2).reverse().toString(); + + //product array. extra leading space for carriers + //normally just need num1.length() + num2.length() -1 + int[] product = new int[num1.length() + num2.length()]; + + //Calculate the product normally + for (int i = 0; i < num1.length(); i++) { + int a = num1.charAt(i) - '0'; + for (int j = 0; j < num2.length(); j++) { + int b = num2.charAt(j) - '0'; + product[i + j] += a * b; + } + } + + //calcualte and output + //remember, now the string is reversed calculated. + //so every time, add to index 0. so it will all reverse back; OR, append, and reverse later. + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < product.length; i++) { + int number = product[i] % 10; + int carrier = product[i] / 10; + sb.append(number); + if (i < product.length - 1) { + product[i + 1] += carrier; + } + } + sb.reverse(); + //trim leading 0's + while (sb.length() > 0 && sb.charAt(0) == '0') { + sb.deleteCharAt(0); + } + + return sb.toString(); + } +} + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Number of Islands.java b/Others/old records/LeetCode-Merged/Java/Number of Islands.java new file mode 100644 index 0000000..cecaee5 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Number of Islands.java @@ -0,0 +1,136 @@ +/* +Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + +Example 1: + +11110 +11010 +11000 +00000 +Answer: 1 + +Example 2: + +11000 +11000 +00100 +00011 +Answer: 3 + + +Tags: Depth-first Search, Breadth-first Search, Union Find +Similar Problems: (M) Surrounded Regions, (M) Walls and Gates + + +*/ + +/* +Attempt2: Use mark to mark all adjacent island. +1. set initial mark = 1 +2. double for loop on each (i,j). +3. mark method: + if a new island found, + a. mark it with mark + b. try to mark all adjacent spot + c. return true + if no new island found, return false; +4. based on returnning value of mark at the double-for loop, increase mark or not. + +return mark - 1, because we set a initial mark == 1, which eases the marking process. but it always has an extra 1. +*/ + +public class Solution { + public int[][] matrix; + public int mark = 1; + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + matrix = new int[grid.length][grid[0].length]; + + for(int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + mark = mark(i, j, grid)? (mark + 1) : mark; + } + } + return mark - 1; + } + + public boolean mark(int i, int j, char[][] grid) { + if (i >= 0 && i < grid.length && j >= 0 && j < grid[0].length) { + if (matrix[i][j] == 0 && grid[i][j] == '1') { + matrix[i][j] = mark; + mark(i - 1, j, grid); + mark(i + 1, j, grid); + mark(i, j - 1, grid); + mark(i, j + 1, grid); + return true; + } + } + return false; + } +} + + +/* +1st attempt, Not working. +Thoughts: +Ues DP to store DP[i][j]: till row i, and element j on row i, what is the number of island we had. + +public class Solution { + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int[][] DP = new int[grid.length][grid[0].length]; + DP[0][0] = grid[0][0] == '1' ? 1 : 0; + int max = DP[0][0]; + int r = grid.length; + int c = grid[0].length; + + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + if (i == 0 && j == 0) { + continue; + } + if(grid[i][j] == '0') { + DP[i][j] = max; + } else {// grid[i][j] == '1' + if (i == 0 && r == 1) { + if (j - 1 >= 0 && DP[i][j - 1] != 0 && grid[i][j - 1] != '0') { + DP[i][j] = max; + } else { + DP[i][j] = max + 1; + max = max + 1; + } + continue; + } + if (j == 0) { + if ((j + 1 < c && grid[i][j + 1] != '0') || (i - 1 >= 0 && grid[i - 1][j] != '0')) { + DP[i][j] = max; + } else { + DP[i][j] = max + 1; + max = max + 1; + } + continue; + } + //DP[i][j] != 0 && Check UP,DOWN, RIGHT, LEFT == 1? + if ((i - 1 >= 0 && DP[i - 1][j] != 0 && grid[i - 1][j] != '0') || + (i + 1 < r && DP[i + 1][j] != 0 && grid[i + 1][j] != '0') || + (j - 1 >= 0 && DP[i][j - 1] != 0 && grid[i][j - 1] != '0') || + (j + 1 < c && DP[i][j + 1] != 0 && grid[i][j + 1] != '0') ) { + DP[i][j] = max; + }else {//NO adjacent is 1 + DP[i][j] = max + 1; + max = max + 1; + } + } + + } + } + + return max; + } +} + +*/ diff --git a/Others/old records/LeetCode-Merged/Java/One Edit Distance.java b/Others/old records/LeetCode-Merged/Java/One Edit Distance.java new file mode 100644 index 0000000..be5351a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/One Edit Distance.java @@ -0,0 +1,55 @@ +理解啥叫Edit。 就是删除,增加,和替换。 +换完之后,理论上换成的String 就应该全等。 +所以只要if statement进去以后,就结束了,总要出一个叫结局。 +``` +/* +Given two strings S and T, determine if they are both one edit distance apart. + +Hide Company Tags Uber Facebook +Hide Tags String +Hide Similar Problems (H) Edit Distance + +*/ + +/* + Thoughts: + One edit distance: delete, insert, and substitude. + For loop. Whenever differenct, chech 3 cases and return + + Note: null cannot become "" or "a", so whenever s or t is null, return false; +*/ + +public class Solution { + public boolean isOneEditDistance(String s, String t) { + if (s == null || t == null) { + return false; + } else if (Math.abs(s.length() - t.length()) > 1 || s.equals(t)) { + return false; + } + int leng = s.length() > t.length() ? t.length() : s.length(); + for (int i = 0; i < leng; i++) { + String ss = s; + String tt = t; + if (s.charAt(i) != t.charAt(i)) { + //Check delete + tt = t.substring(i + 1); + ss = s.substring(i); + if (tt.equals(ss)) { + return true; + } + //Check insert + tt = t.substring(i); + ss = s.substring(i + 1); + if (tt.equals(ss)) { + return true; + } + //check substitude + ss = s.substring(0, i) + s.substring(i + 1); + tt = t.substring(0, i) + t.substring(i + 1); + return ss.equals(tt); + } + }//end for + return true; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Paint Fence.java b/Others/old records/LeetCode-Merged/Java/Paint Fence.java new file mode 100644 index 0000000..5b707c2 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Paint Fence.java @@ -0,0 +1,71 @@ +这题目很有意思. 一开始分析的太复杂, 最后按照这个哥们的想法(http://yuanhsh.iteye.com/blog/2219891) 的来做,反而简单了许多。 +设定T(n)的做法,最后题目化简以后就跟Fibonacci number一样一样的。详细分析如下。 +做完,还是觉得如有神。本来是个Easy题,想不到,就是搞不出。 + +12.13.2015再看了一下: +因为最多2个fence 颜色相同。 +假设i是和 i-1不同,那么结果就是 (k-1)*dp[i - 1] +假设i是何 i-1相同,那么根据条件,i-1和i-2肯定不同。那么所有的结果就是(k-1)*dp[i-2] +加在一起就有了。 +``` +/* +There is a fence with n posts, each post can be painted with one of the k colors. + +You have to paint all the posts such that no more than two adjacent fence posts have the same color. + +Return the total number of ways you can paint the fence. + +Note: +n and k are non-negative integers. + +Tags: Dynamic Programming +Similar Problems: (E) House Robber, (M) House Robber II, (M) Paint House, (H) Paint House II + +*/ + +/* +Thoughts: +Inspiration(http://yuanhsh.iteye.com/blog/2219891) +Consider posts from 1 ~ n. Now we look at last post, marked n: +S(n) means: last 2 fence posts have same color. + Note: S(n) will equal to whatever that's on n-1 position. + Also, just because n and n-1 are same, that means n-2 and n-1 have to be differnet. +SO: +S(n) = D(n - 1) +D(n) means: last 2 fence posts have different color. + Note: for n - 1, and n-2 positions, we have 2 different conditions: + For example: xxy, or wxy, same 2 x's or different w vs. x. +So: +D(n) = (k - 1) * (D(n - 1) + S(n - 1)) + +We can also create T(n) = S(n) + D(n); //T(n) is our totoal results. Will need to return T(n); +Use above equations to figure out T(n) +T(n) = S(n) + D(n) = D(n - 1) + (k - 1) * (D(n - 1) + S(n - 1)) + = D(n - 1) + (k - 1)(T(n - 1)) + = (k - 1) * (D(n - 2) + S(n - 2)) + (k - 1)(T(n - 1)) + = (k - 1)(T(n - 1) + T(n - 2)) + Since n-2 >=1, so n>=3. We need fiture out cases for n = 0,1,2,3 + +Note: +n == 1: just k ways +n == 0: just 0. +k == 0: just 0; +Besides these cases, we are okay. Btw, k does not really matter as long as it's >=1, it can be plugged in. +*/ + +public class Solution { + public int numWays(int n, int k) { + if (n <= 1 || k <= 0) { + return n * k; + } + int[] dp = new int[n + 1]; //index based : 1 + dp[0] = 0; + dp[1] = k; + dp[2] = k + k*(k - 1); + for (int i = 3; i <= n; i++) { + dp[i] = (k - 1) * (dp[i - 1] + dp[i - 2]); + } + return dp[n]; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Palindrome Permutation.java b/Others/old records/LeetCode-Merged/Java/Palindrome Permutation.java new file mode 100644 index 0000000..04fc349 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Palindrome Permutation.java @@ -0,0 +1,91 @@ +注意,条件里面没说是否全是lower case letter +``` +/* +Given a string, determine if a permutation of the string could form a palindrome. + +For example, +"code" -> False, "aab" -> True, "carerac" -> True. + +Hint: + +Consider the palindromes of odd vs even length. What difference do you notice? +Count the frequency of each character. +If each character occurs even number of times, then it must be a palindrome. How about character which occurs odd number of times? + +Tags: Hash Table +Similar Problems: (M) Longest Palindromic Substring, (E) Valid Anagram, (M) Palindrome Permutation II + +*/ + + +/* +Add each char into map. +Count if odd > 1, false + +Note: Iterate HashMap +HashMap.Entry entry : map.entrySet() +*/ + +public class Solution { + public boolean canPermutePalindrome(String s) { + if (s == null || s.length() == 0) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + String str = s.charAt(i) + ""; + if (!map.containsKey(str)) { + map.put(str, 1); + } else { + map.put(str, map.get(str) + 1); + } + }//ENd for + int countOdd = 0; + for (HashMap.Entry entry : map.entrySet()) { + if (entry.getValue() % 2 == 1) { + countOdd++; + } + if (countOdd > 1) { + return false; + } + }//END for + return true; + } +} + + + + +/* +12.12.2015 recap: +use a array of length == 26 to track it? No, because ther ecould be captalized letters, other ASCII code +If with assmption of 26 chars + +AND NO, cannot make that assuption. +*/ +public class Solution { + public boolean canPermutePalindrome(String s) { + if (s == null || s.length() <= 1) { + return true; + } + int[] counts = new int[26]; + for (char c : s.toCharArray()) { + counts[c - 'a'] += 1; + } + int countOne = 0; + for (int count : counts) { + if (count == 1 && countOne >= 1) { + return false; + } else if (count == 1) { + countOne++; + } else if (count % 2 != 0) { + return false; + } + } + + return true; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Peeking Iterator.java b/Others/old records/LeetCode-Merged/Java/Peeking Iterator.java new file mode 100644 index 0000000..8c92076 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Peeking Iterator.java @@ -0,0 +1,141 @@ +再一次理解错题意. peek() 就是头顶,但是不一定是最大值啊。总是把PEEK想成了最大值,然后用2 STACK做了最大值的cache,练的一手好双stack,可惜错了。 + +回到原题,其实不难。找一个cache来存next()的值,然后每次next()里面维护这个cache就好。 + +``` +/* +Given an Iterator class interface with methods: next() and hasNext(), design and implement a PeekingIterator that support the peek() operation -- it essentially peek() at the element that will be returned by the next call to next(). + +Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3]. + +Call next() gets you 1, the first element in the list. + +Now you call peek() and it returns 2, the next element. Calling next() after that still return 2. + +You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false. + +Hint: + +Think of "looking ahead". You want to cache the next element. +Is one variable sufficient? Why or why not? +Test your design with call order of peek() before next() vs next() before peek(). +For a clean implementation, check out Google's guava library source code. (https://github.com/google/guava/blob/703ef758b8621cfbab16814f01ddcc5324bdea33/guava-gwt/src-super/com/google/common/collect/super/com/google/common/collect/Iterators.java#L1125) +Follow up: How would you extend your design to be generic and work with all types, not just integer? + +It looks like the guava library uses 'E' for generic element + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Flatten 2D Vector, (M) Zigzag Iterator + +*/ + +/* +Second attempt. +Thoughts: Of coruse can't store in a queue, that will be brutle and meaning less. +Instead, use a iterator variable, cache, to hold next(). +When called next(), move forward; otherwise, return the cache. +Make sure also return the cached peek, and update cache with next() value. +*/ +// Java Iterator interface reference: +// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html +class PeekingIterator implements Iterator { + private int cache; + private Iterator itt; + private boolean notEnd; + public PeekingIterator(Iterator iterator) { + // initialize any member here. + itt = iterator; + cache = itt.next(); + notEnd = iterator.hasNext(); + } + + // Returns the next element in the iteration without advancing the iterator. + public Integer peek() { + return cache; + } + + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + @Override + public Integer next() { + int curr = cache; + notEnd = itt.hasNext(); + if (itt.hasNext()) { + cache = itt.next(); + } + return curr; + } + + @Override + public boolean hasNext() { + return notEnd; + } +} + + + + +/* +Attempt1, failed. Reason: I thought we are looking for the real max-peek element! However, this problem only asks for peek() element, which is not necessarily the maximun element. This mistake is bloody. +Thoughts: +To find peek, have to run through the iterator at least once. O(n). +Store everything in 2 stacks: +We want to process the end of the iterator first, put everything into stack. +Therefore the top of the stack is the next() element of iterator. +Also, use second stack to hold max value for each element stage. + +Each stack1 element has a max coresponding element in stack2. For example, [5,9,1,3,6] +s1: 6,3,1,9,5 [5 gets out first] +s2: 6,6,6,9,9 [end 9 gets out first] +*/ + +// Java Iterator interface reference: +// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html +class PeekingIterator implements Iterator { + private Stack s1; + private Stack s2; + private int size; + public PeekingIterator(Iterator iterator) { + // initialize any member here. + s1 = new Stack(); + s2 = new Stack(); + Stack temp = new Stack(); + size = 0; + int max = Integer.MIN_VALUE; + while(iterator.hasNext()) { + temp.push(iterator.next()); + size++; + } + while(!temp.empty()) { + s1.push(temp.peek()); + max = Math.max(max, temp.peek()); + s2.push(max); + temp.pop(); + } + } + + // Returns the next element in the iteration without advancing the iterator. + public Integer peek() { + if (s1.size() > size) { + s1.pop(); + return s2.pop(); + } else { + return s2.peek(); + } + } + + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + + @Override + public Integer next() { + size--; + return s1.pop(); + } + + @Override + public boolean hasNext() { + return !s1.empty(); + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Perfect Squares.java b/Others/old records/LeetCode-Merged/Java/Perfect Squares.java new file mode 100644 index 0000000..54a9d9a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Perfect Squares.java @@ -0,0 +1,86 @@ +一开始没clue.看了一下提示。 + +1. 第一步想到了,从数学角度,可能是从最大的perfect square number开始算起。 +2. 然后想法到了dp, 假设最后一步用了最大的maxSqrNum, 那么就在剩下的 dp[i - maxSqrNum^2] +1 不就好了? +3. 做了,发现有个问题...最后一步选不选maxSqrNum? 比如12就是个例子。 + 然后就根据提示,想到BFS。顺的。 把1~maxSqrNum 都试一试。找个最小的。 + 看我把12拆分的那个example. 那很形象的就是BFS了。 + 面试时候,如果拆分到这个阶段不确定,那跟面试官陶瓷一下,说不定也就提示BFS了。 +``` +/* +Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n. + +For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9. + +Credits: +Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Dynamic Programming Breadth-first Search Math +Hide Similar Problems (E) Count Primes (M) Ugly Number II + +*/ +/* +Thoughts: + Math: + num =13. sqrt(13) = 3.xxx. Floor() = 3. count++;//1 + num = 13 - 9 = 4. sqrt(4) = 2. No remaining. count++;//2 + DP: + state + dp[i]: min # of perfect square till i. + dp[0] = 0; + dp[1] = 1; + dp[2] = 1 + 1 = 2; + dp[3] = 1,1,1;//3 + dp[4] = 2^2;//1 + dp[5] = dp[5 - floor(sqrt(5))^2] + 1; + fn: //Pick the largest perfect square possible, then added on what's remaining's dp. Do a BFS on all possiblilities + maxFlorNum = Math.floor(Math.sqrt(i)) + 12 + -3^2 = 3 -2^2 = 8 -1^2 = 11 + 1 + dp[3] 1 + dp[8] 1 + dp[11] + for (j = 0 ~ i) + dp[i] = min(min, dp[i - j ^ 2] + 1) + init: + dp[0] = 0; + dp[1] = 1; + return dp[n]; +*/ + + + +public class Solution { + public int numSquares(int n) { + if (n <= 0) { + return 0; + } + int[] dp = new int[n + 1]; + dp[0] = 0; + + for (int i = 1; i <= n; i++) { + int maxSqrNum = (int)Math.floor(Math.sqrt(i)); + int min = Integer.MAX_VALUE; + for (int j = 1; j <= maxSqrNum; j++) { + min = Math.min(min, dp[i - j * j] + 1); + } + dp[i] = min; + } + return dp[n]; + } +} + + +/* +//Test Cases + dp[2] =2; + dp[4] = 1 + dp[5] = 2; + dp[6] = 2 + 1 =3; + dp[7] = 3 + 1 = 4; + dp[8] = dp[4] + 1 = 1 = 1 = 2; + dp[9] = 1 + dp[10] = 1 + 1 = 2; + dp[11] = 2 + 1 = 3 + dp[12] = dp[12 - 9] + 3 +*/ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Plus One.java b/Others/old records/LeetCode-Merged/Java/Plus One.java new file mode 100644 index 0000000..3a22830 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Plus One.java @@ -0,0 +1,84 @@ +/* +Given a non-negative number represented as an array of digits, plus one to the number. + +The digits are stored such that the most significant digit is at the head of the list. + +Hide Company Tags Google +Hide Tags Array Math +Hide Similar Problems (M) Multiply Strings (E) Add Binary + +*/ + + +public class Solution { + public int[] plusOne(int[] digits) { + if(digits.length==0) return digits; + + digits[digits.length-1] += 1; + //Check index digit.length-1 to 1 + for(int i = digits.length-1; i>0; i--){ + if(digits[i] == 10){ + digits[i]=0; + digits[i-1]+=1; + } + else return digits; + } + + //Check index 0. If ==0, set it to 0 and carry over 1 + if(digits[0]==10){ + int[] output = new int[digits.length+1]; + output[0] = 1; + output[1] = 0; + for(int i=2; i= 0; i--) { + digits[i] += 1; + if (digits[i] != 10) { + return digits; + } + digits[i] = 0; + } + //Create a array with length + 1 + int[] rst = new int[n + 1]; + rst[0] = 1; + rst[1] = 0; + for (int i = 2; i < rst.length; i++) { + rst[i] = digits[i - 1]; + } + return rst; + } +} +/* Trivial solution + create a secondary method func(int index, int[]digits). + add check index from digits.length-1 to 0: digits[index]+1==10? 0 : digits[index]+1; + if add up to 10, push into another level; if not ,return digits. + if index==0, check if add up to 10. If ==10, create a new array and put 1 infront. else return digits. + +*/ diff --git a/Others/old records/LeetCode-Merged/Java/Restore IP Addresses.java b/Others/old records/LeetCode-Merged/Java/Restore IP Addresses.java new file mode 100644 index 0000000..1d4b809 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Restore IP Addresses.java @@ -0,0 +1,89 @@ +递归的终点:list.zie() == 4 +递归在一个index上面(具体问题,具体分析的情况) +validate string要注意leading '0' + +注意: 递归的时候可以用一个start/level/index来跑路 +但是尽量不要去改变Input source, 会变得非常confusing. + +``` +/* + +Given a string containing only digits, restore it by returning all possible valid IP address combinations. + +For example: +Given "25525511135", + +return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) + +Hide Tags Backtracking String + +*/ + +/* + Thoughts: + NOT DONE. NEED CLEAR MIND + Break into 4 parts. + At each index, either close it as one IP spot, or not. + recursive down. + If level == 4 validate if valid IP address. If so, add it. + pass along: rst, list (store the 4 IP spots), level (0 ~ 3), s, + for (0 ~ 2): can pick 1 digit, 2 digits, or 3 digits +*/ +public class Solution { + public List restoreIpAddresses(String s) { + List rst = new ArrayList(); + if (s == null || s.length() == 0) { + return rst; + } + if (s.length() < 4 || s.length() > 12) { + return rst; + } + ArrayList list = new ArrayList(); + helper(rst, list, 0, s); + + return rst; + } + + public void helper(List rst, ArrayListlist, + int start, String s) { + if (list.size() == 4) { + if (start != s.length()) { + return; + } + StringBuffer sb = new StringBuffer(); + for (String str : list) { + sb.append(str + "."); + } + rst.add(sb.substring(0, sb.length() - 1).toString()); + return; + } + //run for loop 3 times: one IP spot has at most 3 digits + for (int i = start; i < s.length() && i <= start + 3; i++) { + String temp = s.substring(start, i + 1); + if (isValid(temp)) { + list.add(temp); + helper(rst, list, i + 1, s); + list.remove(list.size() - 1); + } + } + } + //Valid the IP [0,255]; cannot start with 0 if it's not 0 + public boolean isValid(String str) { + if (str.charAt(0) == '0') { + return str.equals("0"); + } + int num = Integer.parseInt(str); + return num <= 255 && num >= 0; + } + +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Reverse Linked List.java b/Others/old records/LeetCode-Merged/Java/Reverse Linked List.java new file mode 100644 index 0000000..e6af97a --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Reverse Linked List.java @@ -0,0 +1,39 @@ +/* +Reverse a singly linked list. + +Hint: +A linked list can be reversed either iteratively or recursively. Could you implement both? + +Tags: Linked List +Similar Problems: (M) Reverse Linked List II, (M) Binary Tree Upside Down, (E) Palindrome Linked List + +*/ +/* +Thoughts: +Cut off everything from [2 ~ ] and save it in cutoff; +Append old reversed list to current head. Make itself as the new reversedList. Basically: append the 1st element to head of the reversedList, like a stack. +Save head = cutOff: basically moves on to next element. +*/ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + public ListNode reverseList(ListNode head) { + if (head == null) { + return head; + } + ListNode reversedList = null; + while (head != null) { + ListNode cutOff = head.next; + head.next = reversedList; + reversedList = head; + head = cutOff; + } + return reversedList; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Reverse Words in a String II.java b/Others/old records/LeetCode-Merged/Java/Reverse Words in a String II.java new file mode 100644 index 0000000..ba54a7c --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Reverse Words in a String II.java @@ -0,0 +1,65 @@ +/* +Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters. + +The input string does not contain leading or trailing spaces and the words are always separated by a single space. + +For example, +Given s = "the sky is blue", +return "blue is sky the". + +Could you do it in-place without allocating extra space? + +Related problem: Rotate Array + +Tags: String +Similar Problems: (M) Reverse Words in a String, (E) Rotate Array + + +*/ + +/* +Thoughts: write an example: reverse the whole thing, then reverse each individual word, split by space. + +Note: becase we don't have space at end of the char[], so we will ignore last word. Remember to reverse that one. +*/ +public class Solution { + public void reverseWords(char[] s) { + if (s == null || s.length == 0) { + return; + } + int len = s.length; + //reverse whole + for (int i = 0; i < len / 2; i++) { + char temp = s[i]; + s[i] = s[len - 1 - i]; + s[len - 1 - i] = temp; + } + + //reverse partial + int start = 0; + int mid = 0; + int end = 0; + for (int i = 0; i < len; i++) { + if (s[i] == ' ') { + mid = start + (end - start) / 2; + for (int j = start; j <= mid; j++) { + char temp = s[j]; + s[j] = s[end - (j - start)]; + s[end - (j - start)] = temp; + } + start = i + 1; + } else { + end = i; + } + } + + //Process last word + mid = start + (end - start) / 2; + for (int j = start; j <= mid; j++) { + char temp = s[j]; + s[j] = s[end - (j - start)]; + s[end - (j - start)] = temp; + } + + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Rotate Image.java b/Others/old records/LeetCode-Merged/Java/Rotate Image.java new file mode 100644 index 0000000..5ad6129 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Rotate Image.java @@ -0,0 +1,85 @@ +M + +``` +/* +You are given an n x n 2D matrix representing an image. + +Rotate the image by 90 degrees (clockwise). + +Follow up: +Could you do this in-place? + +Tags: +Array +*/ +/* +Thoughts: +Method1: 1. flip the upper half UP/DOWN. 2. Flip the diagal where j >= i + 1 +In place +*/ + +public class Solution { + public void rotate(int[][] matrix) { + if (matrix == null || matrix[0].length == 0) { + return; + } + int n = matrix.length; + //Flip UP/DOWN + for (int i = 0; i < n / 2; i++){ + for (int j = 0; j < n; j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[n - 1 - i][j];//(n-1) is end index, then, matrix[(n-1) - i] means the Symmetry element opposed item matrix[i] + matrix[n - 1 - i][j] = temp; + } + } + //Flip '\' diagnal. + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) {//Skip j = i, which is the diagnal. It's not necessary, so we do j = i + 1 + int temp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = temp; + } + } + } +} + +/* +Method2: Based on method1, we can figure out: if the current position is (i,j), what's the four corresponding positoins? +Then, we just do a overall swap. + +Note: We only do this on the one of the corner in the matrix. Let's do top-left corner. + +About the 4 swapping: +Already figuired out matrix[n-1-i] in method1. +X0 W2 W1 D +X1 Z2 +X2 Z1 +B Y1 Y2 C +1st swap: Use[i] to map [j] is because: + When matching B to X0, and Y1 to X1, and Y2 to X2, X's i is equal to Y' j. We want Y's j increase with X's i increasing. So, map matrix[i][] = matrix[][i] +2nd swap: + Z's i decrease as X's i incease. Same for Z's j +3rd swap: + W's i stable as X's j. However, W's j decrease as X's j increase. +4th swap: + +*/ +public class Solution { + public void rotate(int[][] matrix) { + if (matrix == null || matrix[0].length == 0) { + return; + } + int n = matrix.length; + for (int i = 0; i < n / 2; i++){ + for (int j = 0; j < Math.ceil(n / 2.0); j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[n - 1 - j][i]; + matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j]; + matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i]; + matrix[j][n - 1 - i] = temp; + } + } + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix II.java b/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix II.java new file mode 100644 index 0000000..464bb70 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix II.java @@ -0,0 +1,161 @@ +自己的想法比较老爷车啊。其实一旦想透了就有救。下次试一试自己来画一画来approach。 +题目想法:在右上角开刷,大小不等那么就往唯一可以去的两个方向移动,绝不回头,总可以找到。 +对题目描述的情景和性质要认真考虑清楚再下手。。 +``` +/* +Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: + +Integers in each row are sorted in ascending from left to right. +Integers in each column are sorted in ascending from top to bottom. +For example, + +Consider the following matrix: + +[ + [1, 4, 7, 11, 15], + [2, 5, 8, 12, 19], + [3, 6, 9, 16, 22], + [10, 13, 14, 17, 24], + [18, 21, 23, 26, 30] +] +Given target = 5, return true. + +Given target = 20, return false. + +Tags: Divide and Conquer, Binary Search +Similar Problems: (M) Search a 2D Matrix + +*/ +/* +Attempt3, http://blog.csdn.net/xudli/article/details/47015825 +Do a run through smartly. Think about in a 1D array, we only have 2 directions, which is easy: if less, addup; if more, minus some. +In this relationship, the only we know is: every row, rightside is greater; every column, below is greater. +Magic from that post: set the starting point on right-up-corner, where you only have 2 directions to go: +1. If target is less than curr, move left, j--. (Upper place has nothing, don't go up) +2. If target is more than curr, move down, i++. (right side has ntohing, don't go right) +In next iteration, cut off upper row and right column. Here is the idea: +In 1: target < curr, then target < j+1 , then can put j+1 column on a throw pending +In 2: target > curr, then target > i - 1 row, then can put i - 1 column on a throw pending. +Combine both cases, the upper row and right column will not impact our next iteration, so just imagine we cut them off after dealing with them. +Therefore, in next iteration, we only need to care about the same case again + +*/ +public class Solution { + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + int i = 0; + int j = matrix[0].length - 1; + while (i < matrix.length && j >= 0) { + if (matrix[i][j] == target) { + return true; + } else if (target > matrix[i][j]) { + i++; + } else { + j--; + } + } + return false; + } +} + + + +/* +Attempt2, Thoughts: +1. Targe has to live in a column, so find this column first +2. If target > columnA(i), and target < columA(i+1), then target must be in columnA. +3. Do a binary search on columnA. +However, there is simple counter case: +[ +1, 2, 3, 4, 5, +100,101,102,103,104 +] +Look for 100. +Won't work in below code, because when I do binary search on 1st row, it goes all across the row but can't identify that the target is actually in front columns. This is beacuse, the end of 1st row does not have a meaningful relationship with the head of 2nd row. +It fails on locating the correct column. And code is too long ... +*/ +/* + +public class Solution { + public static boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + + int m = matrix.length; + int n = matrix[0].length; + int start = 0; + int end = matrix[0].length - 1; + int i = 0; + int j = 0; + int mid; + int col = -1; + //Find column + while (start + 1 < end) { + mid = start + (end - start) / 2; + j = mid; + if (matrix[i][j] == target) { + return true; + } else if (j + 1 < n && matrix[i][j] < target && target < matrix[i][j + 1]) { + col = j; + break; + } else if (j - 1 >= 0 && matrix[i][j - 1] < target && target < matrix[i][j]) { + col = j - 1; + break; + } else if (target > matrix[i][j]) { + start = mid; + } else if (target < matrix[i][j]) { + end = mid; + } + } + if (col == -1) {//1 + j = end; + col = target >= matrix[i][j] ? end : start; + } + + //Find target + start = 0; + end = m - 1; + j = col; + while (start + 1 < end) { + mid = start + (end - start) / 2; + i = mid; + if (matrix[i][j] == target) { + return true; + } else if (target > matrix[i][j]) { + start = mid; + } else if (target < matrix[i][j]) { + end = mid; + } + }//End while + return matrix[start][j] == target || matrix[end][j] == target; + } +} + +*/ + +/* +Attempt1, Thoughts: +But not correct: because the mid point calculation is based on linear relationship between start and end. In this problem, the relationship is not linear. +The following idea only considers the way to jump to different spots, but didn't take care of how to generate the mid index in the first place. +Each spot has 3 direction to go for larget element, and another 3 directions to go for smaller element. +If match, return true; +If target is greater than mid, move start to large element around mid + if target > (i+1,j+1) : start = (i+1, j+1) + if target > (i,j+1) : start = (i, j+1) + if target > (i+1,j) : start = (i+1, j) +If target is less than mid, move end to small element around mid + if target < (i-1,j-1) : end = (i-1,j-1) + if target < (i,j-1) : end = (i, j-1) + if target < (i-1,j) : end = (i-1, j) +init: +start = 0 +end = m*n - 1; + +However, mid = start + (end - start) / 2; won't work here. +*/ + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix.java b/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix.java new file mode 100644 index 0000000..ced63f7 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Search a 2D Matrix.java @@ -0,0 +1,63 @@ +曾经有过。2D转1D。注意 行 = index/宽度 ; 列 = index%宽度。 +``` +/* +Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: + +Integers in each row are sorted from left to right. +The first integer of each row is greater than the last integer of the previous row. +For example, + +Consider the following matrix: + +[ + [1, 3, 5, 7], + [10, 11, 16, 20], + [23, 30, 34, 50] +] +Given target = 3, return true. + +Tags: Array, Binary Search +Similar Problems: (M) Search a 2D Matrix II + +*/ + +/* +Thought: +Binary search. +Treat 2D matrix as a 1D array. spot = m * i + j; +start = 0; +end = m * n - 1; +*/ +public class Solution { + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + int m = matrix.length; + int n = matrix[0].length; + int start = 0; + int end = m * n - 1; + int mid; + int i; + int j; + while (start + 1 < end) { + mid = start + (end - start) / 2; + i = mid / n; + j = mid % n; + if (matrix[i][j] == target) { + return true; + } else if (matrix[i][j] > target) { + end = mid; + } else { + start = mid; + } + } + int s1 = start / n; + int s2 = start % n; + int e1 = end / n; + int e2 = end % n; + + return matrix[s1][s2] == target || matrix[e1][e2] == target; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/String to Integer.java b/Others/old records/LeetCode-Merged/Java/String to Integer.java new file mode 100644 index 0000000..81c7042 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/String to Integer.java @@ -0,0 +1,60 @@ +/* +Implement atoi to convert a string to an integer. + +Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases. + +Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front. +*/ + +/* +Thoughts: +Ask for requirement, and ajust the code: +Requirements for atoi: +The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. + +The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function. + +If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed. + +If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. +*/ + +public class Solution { + public int myAtoi(String str) { + if (str == null || str.length() == 0) { + return 0; + } + String sign = ""; + String digits = ""; + char[] arr = str.toCharArray(); + for (int i = 0; i < arr.length; i++) { + if (digits.length() == 0 && sign.length() == 0) { + if (arr[i] == '+' || arr[i] == '-') { + sign = arr[i] + ""; + continue; + } else if (arr[i] == ' ') { + continue; + } else if (arr[i] < '0' || arr[i] > '9') { + break; + } + }//END: integer haven't begin, but can take '+/-' and skip space + + if (arr[i] >= '0' && arr[i] <= '9') { + digits += arr[i]; + } else { + break; + } + } + if (digits.length() == 0) {//Check if empty() + return 0; + } + if (digits.length() > 10) {//Check if we have more than 10 digits. It's here because it can exceed Long's MAX as well. + return sign.equals("-") ? Integer.MIN_VALUE: Integer.MAX_VALUE; + } + long rst = Long.parseLong(digits) * (sign.equals("-") ? -1 : 1); + if (rst > Integer.MAX_VALUE || rst < Integer.MIN_VALUE ) {//Double check if digits is within Integer's MAX and MIN + return rst > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + return (int)rst;//Convert long to int + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number II.java b/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number II.java new file mode 100644 index 0000000..9d47fa6 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number II.java @@ -0,0 +1,73 @@ +耗了一点时间。本以为需要DP一下,把做过的n存一下。后来发现,其实就是剥皮,一层一层,是一个central-depth-first的,钻到底时候,return n=1,或者n=2的case,然后开始backtracking。 +难的case先不handle.到底之后来一次O(n) scan. +总共的时间起码是O(n/2) + O(n), 所以还是O(n) +``` +/* +A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). + +Find all strobogrammatic numbers that are of length = n. + +For example, +Given n = 2, return ["11","69","88","96"]. + +Hint: +Try to use recursion and notice that it should recurse with n - 2 instead of n - 1. + +Tags: Math Recursion +Similar Problems: (E) Strobogrammatic Number, (H) Strobogrammatic Number III + +*/ +/* +Thoughts: +For n, there can be k kinds of combination. Save it to map(n,k-list) +For n+2, there can be x + k-kinds-of-inner-number + y; +Treat n=0,1,2 differently. Then recurse on rest, layer by layer +At end end, do a O(n) scan to remove non-wanted items. +*/ +public class Solution { + private HashMap candidate = new HashMap(); + public List findStrobogrammatic(int n) { + List rst = new ArrayList(); + candidate.put("0", "0"); + candidate.put("1", "1"); + candidate.put("8", "8"); + candidate.put("6", "9"); + candidate.put("9", "6"); + rst = searchAndCombine(n); + for (int i = 0; i < rst.size(); i++) { + if ((Long.parseLong(rst.get(i))+"").length() != n) { + rst.remove(i); + i--; + } + } + return rst; + } + + public List searchAndCombine(int n) { + List list = new ArrayList(); + if (n <= 0) { + return list; + } else if (n == 1) { + list.add("0"); + list.add("1"); + list.add("8"); + return list; + } else if (n == 2){ + list.add("69"); + list.add("11"); + list.add("88"); + list.add("96"); + list.add("00"); + return list; + }else {//n >= 2 + List temp = searchAndCombine(n - 2); + for (String str : temp) { + for (Map.Entry entry : candidate.entrySet()) { + list.add(entry.getKey() + str + entry.getValue()); + } + } + } + return list; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number.java b/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number.java new file mode 100644 index 0000000..9d7d0eb --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Strobogrammatic Number.java @@ -0,0 +1,83 @@ +/* +A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). +Write a function to determine if a number is strobogrammatic. The number is represented as a string. +For example, the numbers "69", "88", and "818" are all strobogrammatic. +Tags: Hash Table Math +Similar Problems: (M) Strobogrammatic Number II, (H) Strobogrammatic Number III +*/ + +/* +OPTS 11.04.2015 +Thoughts: +Because the symmetric pairs are: +1-1, 8-8,0-0,6-9,9-6, we make a hashmap of it. +Create left/right pointer, where each compare has to match the pair in hashmap. + +Note: +On map.containsKey() line, need to check (right), or whichever item that map is going to map.get(...) afterwards. +If containsKey fails, return false; only when it passes through, then proceed to mpa.get() +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + HashMap map = new HashMap(); + map.put('0','0'); + map.put('1','1'); + map.put('8','8'); + map.put('6','9'); + map.put('9','6'); + int left = 0; + int right = num.length() - 1; + while (left <= right) { + if (!map.containsKey(num.charAt(right)) || num.charAt(left) != map.get(num.charAt(right))) { + return false; + } + left++; + right--; + } + return true; + } +} + +/* +Thoughts: +Compare digits to the symmetric postion; special care for (6,9) pair, mark it after comparision. +Elimite the cases before the for-loop run through(can do it in or as well, but that just make the code a bit complex) +Note: +Didn't use HashMap. I beleive hash map is used to mark the spot? +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + //Any non-strobogrammatic + if (num.indexOf("2") >= 0 || num.indexOf("3") >= 0 || + num.indexOf("4") >= 0 || num.indexOf("5") >= 0 || + num.indexOf("7") >= 0) { + return false; + } + //If only 6 or 9 exist: + if ((num.indexOf("6") >= 0 && num.indexOf("9") < 0) || + (num.indexOf("9") >= 0 && num.indexOf("6") < 0)) { + return false; + } + //Check if (6,9) or other strobogrammatic # are appearing at symmetric position + char[] arr = num.toCharArray(); + int leng = num.length(); + for (int i = 0; i < leng; i++) { + if (arr[i] == '6' || arr[i] == '9') { + if ((arr[i] == '6' && arr[leng - i - 1] != '9') || + (arr[i] == '9' && arr[leng - i - 1] != '6')) { + return false; + } + arr[i] = arr[leng - i - 1] = 'M';//marker + } else if (arr[i] != 'M' && arr[i] != arr[leng - i - 1]) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Summary Ranges.java b/Others/old records/LeetCode-Merged/Java/Summary Ranges.java new file mode 100644 index 0000000..f6370f5 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Summary Ranges.java @@ -0,0 +1,37 @@ +/* +Given a sorted integer array without duplicates, return the summary of its ranges. + +For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. + +Tags: Array +Similar Problems: (M) Missing Ranges + + +*/ +/* +Thoughts: basic implementation, use a arraylist to catch candidates. +Detect condition, and return results. +*/ +public class Solution { + public List summaryRanges(int[] nums) { + List rst = new ArrayList(); + if (nums == null || nums.length == 0) { + return rst; + } + ArrayList list = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + list.add(nums[i]); + if (i + 1 == nums.length || nums[i] + 1 != nums[i + 1]) { + if (list.size() == 1) { + rst.add(list.get(0) + ""); + } else { + rst.add(list.get(0) + "->" + list.get(list.size() - 1)); + } + list = new ArrayList(); + } + } + return rst; + } +} + +//O(n) \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Surrounded Regions.java b/Others/old records/LeetCode-Merged/Java/Surrounded Regions.java new file mode 100644 index 0000000..3cb5138 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Surrounded Regions.java @@ -0,0 +1,152 @@ +/* +Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. + +A region is captured by flipping all 'O's into 'X's in that surrounded region. + +For example, +X X X X +X O O X +X X O X +X O X X +After running your function, the board should be: + +X X X X +X X X X +X X X X +X O X X +Hide Tags Breadth-first Search + +Thinking Process: +Since dfs does not work, try bfs. +Very similar to DFS, however, when checking the 4 bounaries: +1. chcek the curruent point. +2. Add surrounding points into a queue. +3. Deal with the queue immediately via a while loop + +*/ +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + private Queue queue = new LinkedList(); + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + row = board.length; + col = board[0].length; + target = 'O'; + mark = 'M'; + //Check the board + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || i == row - 1 || j == 0 || j == col - 1) { + check(i,j); + } + } + } + //Replacement + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } + if (board[i][j] == mark) { + board[i][j] = target; + } + } + } + } + //BFS + public void check(int i, int j) { + fill(board, i, j); + while(!queue.isEmpty()) { + int val = queue.poll(); + int x = val / col; + int y = val % col; + fill(board, x - 1, y); + fill(board, x + 1, y); + fill(board, x, y - 1); + fill(board, x, y + 1); + } + } + public void fill(char[][] board, int i, int j) { + if (i < 0 || i >= row || j < 0 || j >= col || board[i][j] != target) { + return; + } + board[i][j] = mark; + queue.offer(i * col + j); + } +} + + + + +/* +Thinking process: +Using DFS. +1. Whenever the edge has an 'O', all touching point with 'O' will be non-surrounded by 'X'. SO check the 4 bounds first. Mark all non-surrounded point as M. +2. Replace all remaining 'O' with 'X' +3. Replace 'M' with 'O' +However, in the LeetCode test, DFS gives stack overflow. So we'd use BFS instead. +*/ + +/* + +//The following is using DFS, but gives Stackoverflow. +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + target = 'O'; + mark = 'M'; + row = board.length; + col = board[0].length; + + //check bound + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || j == 0 || i == row - 1 || j == col - 1) { + check(i, j); + } + } + } + //1. replace remaining target with 'x' + //2. replace all mark with 'O' + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } else if (board[i][j] == mark) { + board[i][j] = 'O'; + } + } + } + } + + public void check(int i, int j) { + if (i < 0 || j < 0 || i > row - 1 || j > col - 1) { + return; + } + if (board[i][j] == target) { + board[i][j] = mark; + check(i - 1, j); + check(i + 1, j); + check(i, j - 1); + check(i, j + 1); + } + } + +} + +*/ diff --git a/Others/old records/LeetCode-Merged/Java/Symmetric Binar Tree.java b/Others/old records/LeetCode-Merged/Java/Symmetric Binar Tree.java new file mode 100644 index 0000000..a4cb826 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Symmetric Binar Tree.java @@ -0,0 +1,93 @@ +注意Symmetric Binary Tree的例子和定义。 +并不是说左右两个tree相等。 +``` +/* +Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). + +For example, this binary tree is symmetric: + + 1 + / \ + 2 2 + / \ / \ +3 4 4 3 +But the following is not: + 1 + / \ + 2 2 + \ \ + 3 3 +Note: +Bonus points if you could solve it both recursively and iteratively. + +confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. + +Hide Tags Tree Depth-first Search + +*/ +/* + Recursive +*/ +public class Solution { + /** + * @param root, the root of binary tree. + * @return true if it is a mirror of itself, or false. + */ + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + return check(root.left, root.right); + } + + public boolean check(TreeNode A, TreeNode B) { + if (A == null && B == null) { + return true; + } else if (A == null || B == null) { + return false; + } + return A.val == B.val && check(A.left, B.right) && check(A.right, B.left); + } +} + + +//Non-recursive, iterative +/* + Thoughts: + Use 2 stack to hold the child that's needed to compare. + Have to use stack, otherwise, can't iterate through root node. +*/ + +public class Solution { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + s1.push(root.left); + s2.push(root.right); + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode node1 = s1.pop(); + TreeNode node2 = s2.pop(); + if (node1 == null && node2 == null) { + continue; + } else if (node1 == null || node2 == null) { + return false; + } else if (node1.val != node2.val) { + return false; + } + s1.push(node1.left); + s2.push(node2.right); + s1.push(node1.right); + s2.push(node2.left); + } + + return true; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Trapping Rain Water.java b/Others/old records/LeetCode-Merged/Java/Trapping Rain Water.java new file mode 100644 index 0000000..adc5f7d --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Trapping Rain Water.java @@ -0,0 +1,137 @@ +/* +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. + +Example +Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. + +Challenge +O(n) time and O(1) memory + +O(n) time and O(n) memory is also acceptable. + +Tags Expand +Two Pointers Forward-Backward Traversal Array + +Related Problems Expand +Medium Container With Most Water + +LeetCode: +Tags: Array, Stack, Two Pointers +Similar Problems: (M) Container With Most Water, (M) Product of Array Except Self + + +*/ +/* +Solution2: imagine there is always 2 bar that holds the water in middle; or imagine: we only have one side of the wall (right wall in this case), +and we are adding a hard-paper on leftside of the water, thus we can calculate the volumn of water in middle. +Idea is: two artificial wall has to both > water in middle, then will have water in middle. +Also, another idea of shifting highest wall: the highest wall from left and highest wall from right will hold a triangle shape of water in between, +when calculating the water in middle index by index, we can simulate the two walls in by comparing max. +Note: the true volumn for each index calculated should respect the min of the 2 highest walls. + +Note2: leftSideHighWall always store the heigest wall on left side of current index. +*/ +public class Solution { + public int trap(int[] heights) { + if (heights == null || heights.length == 0) { + return 0; + } + int[] leftSideHighWall = new int[heights.length + 1]; + leftSideHighWall[0] = 0; + for (int i = 0; i < heights.length; i++) { + leftSideHighWall[i + 1] = Math.max(leftSideHighWall[i], heights[i]); + } + int rightSideHighWall = 0; + int sum = 0; + for (int i = heights.length - 1; i >= 0; i--) { + int minOfTwoWalls = Math.min(leftSideHighWall[i], rightSideHighWall); + sum += minOfTwoWalls > heights[i] ? minOfTwoWalls - heights[i] : 0; + rightSideHighWall = Math.max(heights[i], rightSideHighWall); + } + return sum; + } +} + +/* +Solution1, Add extra and remove extra +Thoughts: +1. Find max's index, and use this index as the central pivot. (WHY? because highest bar can hold any volumn of water) +2. Process left and right separately. + a. assume each height jump fills that increased height of volumn. that is, if increased by r rows, add r rows of water into sum + b. all the black blocks (stones) should be minus from the sum on each index. +O(n) on finding the max. +O(n/2) for both left and right. +Total 2*O(n) = O(n) + +*/ + + + + +public class Solution { + /** + * @param heights: an array of integers + * @return: a integer + */ + public int trap(int[] heights) { + if (heights == null || heights.length == 0) { + return 0; + } + int max = 0; + int maxIndex = -1; + int sum = 0; + int prev; + for (int i = 0; i < heights.length; i++) { + if (heights[i] > max) { + max = heights[i]; + maxIndex = i; + } + } + + //Process left + prev = 0; + for (int i = 0; i < maxIndex; i++) { + if (heights[i] > prev) { + sum += (heights[i] - prev) * (maxIndex - i); + prev = heights[i]; + } + sum -= heights[i]; + } + + //Process right: + prev = 0; + for (int i = heights.length - 1; i > maxIndex; i--) { + if (heights[i] > prev) { + sum += (heights[i] - prev) * (i - maxIndex); + prev = heights[i]; + } + sum -= heights[i]; + } + + return sum; + } + + } + +} + + + + + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LeetCode-Merged/Java/Two Sum II - Input array is sorted.java b/Others/old records/LeetCode-Merged/Java/Two Sum II - Input array is sorted.java new file mode 100644 index 0000000..f061dd9 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Two Sum II - Input array is sorted.java @@ -0,0 +1,46 @@ +/* +Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 + +Tags: Array Two Pointers, Binary Search +Similar Problems: (M) Two Sum + +*/ + + +/* +Thoughts: +Do a binary search, but do not over-complicate it: +Start, end. Check if nums[start] + nums[end] == target. +binary move it: in fact, moving the two border, 1 position at a time +*/ + +public class Solution { + public int[] twoSum(int[] nums, int target) { + int[] rst = new int[2]; + if (nums == null || nums.length <= 1) { + return rst; + } + int start = 0; + int end = nums.length - 1; + while(start < end) { + long sum = (long)(nums[start] + nums[end]); + if (target == sum) { + rst[0] = start + 1; + rst[1] = end + 1; + break; + } else if (target > sum) { + start++; + } else { + end--; + } + }//END while + return rst; + } +} diff --git a/Others/old records/LeetCode-Merged/Java/Two Sum.java b/Others/old records/LeetCode-Merged/Java/Two Sum.java new file mode 100644 index 0000000..2afb271 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Two Sum.java @@ -0,0 +1,40 @@ +/* +Given an array of integers, find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 + +Array, Hash Table +Similar Problems: (M) 3Sum, (M) 4Sum (M), Two Sum II - Input array is sorted, (E) Two Sum III - Data structure design + +*/ + +/* +Thought: +Hash added value . +Check remaining value == target ? +*/ +public class Solution { + public int[] twoSum(int[] nums, int target) { + int[] rst = new int[2]; + if (nums == null || nums.length <= 1) { + return rst; + } + HashMap map = new HashMap(); + for (int i = 0; i < nums.length; i++) { + int remaining = target - nums[i]; + if (!map.containsKey(remaining)) { + map.put(nums[i], i); + } else { + rst[0] = map.get(remaining) + 1; + rst[1] = i + 1; + break; + } + } + return rst; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Ugly Number II.java b/Others/old records/LeetCode-Merged/Java/Ugly Number II.java new file mode 100644 index 0000000..cbeae40 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Ugly Number II.java @@ -0,0 +1,76 @@ +非常brutle的。 +每次把dp[i-1]拿出来,不管三七二十一,分别乘以2,3,5. 出来的结果放进priority queue做比较。 +最后时间是n*log(n*3) + +注意: +Long +HashSet确保没有重复。 +``` +/* +Write a program to find the n-th ugly number. + +Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. +For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers. + +Note that 1 is typically treated as an ugly number. +*/ + +/* + Thought: + Could do a infinite while loop, check each number see if that's an ugly number; till we find the nth. + time = m * O(avg # of factors for each integer) [m is probably a lot greater than n]~= O(m^2) + + So we definitely need to calculate it: + if we know a number x is ugly, we can *2, *3, *5 to make furture ugly numbers. + State: + dp[i]: ith ugly number. + fn: + candidate: Priority queue to hold candiates. + A HashSet() that makes sure dp[i-1]*2/3/5 is not duplicate. + candidate.add(dp[i - 1] * 2) + candidate.add(dp[i - 1] * 3) + candidate.add(dp[i - 1] * 5) + dp[i] = candidate.poll(); + init: + dp[0] = 0; + dp[1] = 1; + + return dp[n] + +Note: some number * 5 could be long. Just make sure it's long, then convert to int at the end. +*/ + +public class Solution { + public int nthUglyNumber(int n) { + if (n <= 0) { + return 0; + } else if (n == 1) { + return 1; + } + long[] dp = new long[n + 1]; + dp[0] = 0; + dp[1] = 1; + + PriorityQueue candidate = new PriorityQueue(); + HashSet set = new HashSet(); + set.add(dp[1]); + for (int i = 2; i <= n; i++) { + if (!set.contains(dp[i - 1] * 2)) { + candidate.add(dp[i - 1] * 2); + set.add(dp[i - 1] * 2); + } + if (!set.contains(dp[i - 1] * 3)) { + candidate.add(dp[i - 1] * 3); + set.add(dp[i - 1] * 3); + } + if (!set.contains(dp[i - 1] * 5)) { + candidate.add(dp[i - 1] * 5); + set.add(dp[i - 1] * 5); + } + dp[i] = candidate.poll(); + } + + return (int)dp[n]; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Ugly Number.java b/Others/old records/LeetCode-Merged/Java/Ugly Number.java new file mode 100644 index 0000000..dc8cc4e --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Ugly Number.java @@ -0,0 +1,44 @@ +/* +Write a program to check whether a given number is an ugly number. + +Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. +For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7. + +Note that 1 is typically treated as an ugly number. + + +Hide Tags Math +Hide Similar Problems (E) Happy Number (E) Count Primes (M) Ugly Number II + +*/ +/* + Thoughts: + Find all prime factors, check if other factors exist rather than 2,3,5. + 3 while loops. + If num % 5 = 0 , keep it going. + If num % 3 = 0, keep it going. + If num % 2 = 0, keep it going ... + At the end, it should == 1. If not, return false; +*/ + + +public class Solution { + public boolean isUgly(int num) { + if (num <= 0) { + return false; + } else if (num == 1) { + return true; + } + + while (num != 0 && num % 5 == 0) { + num = num / 5; + } + while (num != 0 && num % 3 == 0) { + num = num / 3; + } + while (num != 0 && num % 2 == 0) { + num = num / 2; + } + return num == 1; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Unique Word Abbreviation.java b/Others/old records/LeetCode-Merged/Java/Unique Word Abbreviation.java new file mode 100644 index 0000000..f4a48f3 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Unique Word Abbreviation.java @@ -0,0 +1,91 @@ +/* +An abbreviation of a word follows the form . Below are some examples of word abbreviations: + +a) it --> it (no abbreviation) + + 1 +b) d|o|g --> d1g + + 1 1 1 + 1---5----0----5--8 +c) i|nternationalizatio|n --> i18n + + 1 + 1---5----0 +d) l|ocalizatio|n --> l10n +Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation. + +Example: +Given dictionary = [ "deer", "door", "cake", "card" ] + +isUnique("dear") -> false +isUnique("cart") -> true +isUnique("cane") -> false +isUnique("make") -> true + +Tags: Hash Table, Design +Similar Problems: (E) Two Sum III - Data structure design + + + +*/ +/* +Thought: +Originally, used a hashset to store all existing pattern. If checked word exist in dict hashset, then return false. +However, there is a case that: the word existed in the dict only for once, which is by accident the same as the checked work, then return true. +Therefore, we need to keep track of what word has been catagrize into pattern. SO, use a HashMap instead. + +Note: Dealing with char, integer, string. Be careful if char are turnning int integers. +*/ +public class ValidWordAbbr { + HashMap> map; + public ValidWordAbbr(String[] dict) { + if (dict == null || dict.length == 0) { + return; + } + map = new HashMap>(); + for (String s : dict) { + String str = ""; + if (s.length() <= 2) { + str = s; + } else { + str += s.charAt(0) + (s.length() - 2 + "") + s.charAt(s.length() - 1); + } + if (!map.containsKey(str)) { + ArrayList list = new ArrayList(); + list.add(s); + map.put(str, list); + } else { + if (!map.get(str).contains(s)) { + map.get(str).add(s); + } + + } + } + } + + public boolean isUnique(String word) { + if (map == null || map.size() == 0) { + return true; + } + String str = ""; + if (word.length() <= 2) { + str = word; + } else { + str += word.charAt(0) + (word.length() - 2 + "") + word.charAt(word.length() - 1); + } + if (map.containsKey(str) && map.get(str).size() == 1 && map.get(str).get(0).equals(word)) { + return true; + } + return !map.containsKey(str); + } +} + + + + + +// Your ValidWordAbbr object will be instantiated and called as such: +// ValidWordAbbr vwa = new ValidWordAbbr(dictionary); +// vwa.isUnique("Word"); +// vwa.isUnique("anotherWord"); \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Valid Anagram.java b/Others/old records/LeetCode-Merged/Java/Valid Anagram.java new file mode 100644 index 0000000..177b324 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Valid Anagram.java @@ -0,0 +1,58 @@ +/* +Given two strings s and t, write a function to determine if t is an anagram of s. + +For example, +s = "anagram", t = "nagaram", return true. +s = "rat", t = "car", return false. + +Note: +You may assume the string contains only lowercase alphabets. + +Follow up: +What if the inputs contain unicode characters? How would you adapt your solution to such case? + +Tags: Hash Table, Sort +Similar Problems: (M) Group Anagrams, (E) Palindrome Permutation + + +*/ +/* +Thoughts: +Anagram: reorder of letters. +Use HashMap to store the frequency of chars of 1st string, and check aginst 2nd string. +s character: +1; +t character: -1; +check count of each index in the map; they should all be 0 +*/ + + +public class Solution { + public boolean isAnagram(String s, String t) { + if (s == null || t == null) { + return s == null && t == null; + } else if (s.length() != t.length()) { + return false; + } + + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + if (!map.containsKey(s.charAt(i))) { + map.put(s.charAt(i), 1); + } else { + map.put(s.charAt(i), map.get(s.charAt(i)) + 1); + } + if (!map.containsKey(t.charAt(i))) { + map.put(t.charAt(i), -1); + } else { + map.put(t.charAt(i), map.get(t.charAt(i)) - 1); + } + }//END for + + for (int i = 0; i < s.length(); i++) { + if (map.get(s.charAt(i)) != 0) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Valid Parentheses.java b/Others/old records/LeetCode-Merged/Java/Valid Parentheses.java new file mode 100644 index 0000000..98afe40 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Valid Parentheses.java @@ -0,0 +1,114 @@ +/* +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. + +Tags: Stack, String +Similar Problems: (M) Generate Parentheses, (H) Longest Valid Parentheses +*/ +/* +Attemp3: http://fisherlei.blogspot.com/2013/01/leetcode-valid-parentheses.html +Use stack. + +If the incoming char is '(,{,[', add on top. +Otherwise, check incoming char against stack.peek(), and see if they are '),},]'. If not, false. +It's the natural process of checking the parentheses by looking at the most inner circle; well, easist is just to use a stack to hold the front part of parentheses. + +Note: +Stack: isEmpty(), empty() +Be careful with the case '[])' where stack could be empty, but we still try to peek() it. +*/ +public class Solution { + public boolean isValid(String s) { + if (s == null || s.equals("()") || s.equals("{}") ||s.equals("[]")) { + return true; + } + char[] arr = s.toCharArray(); + Stack stack = new Stack(); + stack.push(arr[0]); + for (int i = 1; i < s.length(); i++) { + if ("({[".indexOf(arr[i]+"") != -1) { + stack.push(arr[i]); + continue; + } + if (stack.isEmpty()) { + return false; + } + if (arr[i] == ')' && stack.peek() != '(') { + return false; + } + if (arr[i] == '}' && stack.peek() != '{') { + return false; + } + if (arr[i] == ']' && stack.peek() != '[') { + return false; + } + stack.pop(); + } + if (!stack.isEmpty()) { + return false; + } + return true; + } +} + +/* +2nd attempt failed. +Recursive: when one block is correct, the stuff inside of them must be correct. +Incorrect: for some cases. +*/ +public class Solution { + public boolean isValid(String s) { + if (s == null || s.equals("()") || s.equals("{}") ||s.equals("[]")) { + return true; + } + if (s.length() % 2 == 1) { + return false; + } + char c = s.charAt(0); + int index = 0; + switch (c) { + case '(' : index = s.indexOf(')'); break; + case '{' : index = s.indexOf('}'); break; + case '[' : index = s.indexOf(']'); break; + default: index = -1; break; + } + + if (index == -1) { + return false; + } + + boolean middle = isValid(s.substring(1, index)); + boolean after = (index == s.length() - 1) ? true : isValid(s.substring(index)); + + return middle && after; + } +} + +/* +First attemp, Thoughts: +break into char array. +Count against each char + +However didnt consider :"([)]". failed +*/ + +public class Solution { + public boolean isValid(String s) { + if (s == null) { + return true; + } + int[] count = new int[3]; + for (char c : s.toCharArray()) { + switch (c) { + case '(' : count[0]++; break; + case ')' : count[0]--; break; + case '{' : count[1]++; break; + case '}' : count[1]--; break; + case '[' : count[2]++; break; + case ']' : count[2]--; break; + } + } + return (count[0] + count[1] + count[2]) == 0; + } +} \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Validate Binary Search Tree.java b/Others/old records/LeetCode-Merged/Java/Validate Binary Search Tree.java new file mode 100644 index 0000000..36e20af --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Validate Binary Search Tree.java @@ -0,0 +1,73 @@ +注意带有upper/lower bound. +定义:binary search tree, 左边的所有node都比root和右边的小;右边的所有node都比root和左边的大。 +最短的这个解法,判断对的case,其余false. + +``` +/* +Given a binary tree, determine if it is a valid binary search tree (BST). + +Assume a BST is defined as follows: + The left subtree of a node contains only nodes with keys less than the node's key. + The right subtree of a node contains only nodes with keys greater than the node's key. + Both the left and right subtrees must also be binary search trees. + +confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ. + +Tags: Tree Depth-first Search +Similar Problems: (M) Binary Tree Inorder Traversal + +*/ + +/*Current solution: Do the same as before, however, make sure to add MIN and MAX in the recursive funtion + +Note: becareful with Integer MAX and MIN. Use Long MAX and MIN +*/ + + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public boolean isValidBST(TreeNode root) { + return check(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + public boolean check(TreeNode node, long MIN, long MAX) { + if (node == null) { + return true; + } + if (node.val > MIN && node.val < MAX && + check(node.left, MIN, node.val) && + check(node.right, node.val, MAX)) { + return true; + } else { + return false; + } + } +} + + + +//Another long solution, check false case and return the true case. +//NOTE: be careful with the false case on '==' +public class Solution { + public boolean isValidBST(TreeNode root) { + return check(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + public boolean check(TreeNode node, long MIN, long MAX) { + if (node == null) { + return true; + } + if (node.val >= MAX || node.val <= MIN) { + return false; + } + return check(node.left, MIN, node.val) && check(node.right, node.val, MAX); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Wiggle Sort.java b/Others/old records/LeetCode-Merged/Java/Wiggle Sort.java new file mode 100644 index 0000000..b467cbc --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Wiggle Sort.java @@ -0,0 +1,92 @@ +第一遍想太多. 其实做一个fall-through就能把问题解决,原因是因为: +这样的fall-through每次在乎两个element,可以一口气搞定,无关乎再之前的elements。 +特别的一点:flag来巧妙的掌控山峰和低谷的变化。又是神奇的一幕啊! + +这样子的奇观,见过就要知道了,没见过的时候有点摸不着头脑。 +``` +/* +Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3].... + +For example, given nums = [3, 5, 2, 1, 6, 4], one possible answer is [1, 6, 2, 5, 3, 4]. + +Tags: Array Sort +Similar Problems: (M) Sort Colors + +*/ + +/* +Attemp2, Thoughts: (http://www.cnblogs.com/easonliu/p/4798814.html) +Draw wiggle on original array. Whenever any postion i is not working with i-1, swap them. +Cases: +1. when nums[i] is supposed to >= nums[i - 1], however it's nums[i] < nums[i - 1], swap them. For example (nums[1] vs. nums[0]) +2. when nums[i] is supposed to <= nums[i - 1], however it's nums[i] > nums[i - 1], swap them. For example (nums[2] vs. nums[1]) +Specially, for case 2: can times a -1 on both side, to make nums[i] * -1 < nums[i - 1] * -1. Therefore we only need 1 if statement. + +Concept: whenver something does not work, fix it. (especailly now we are only taking caer of 2 elements at a time, so we can do it as a fall-through) +*/ +public class Solution { + public void wiggleSort(int[] nums) { + if (nums == null || nums.length <= 1) { + return; + } + int flag = 1; + for (int i = 1; i < nums.length; i++) { + if (flag * nums[i] < flag * nums[i - 1]) { + swap(nums, i, i - 1); + } + flag = -1 * flag; + } + } + + public void swap(int[] nums, int x, int y) { + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } +} + + +/* +Attempt1: +Wiggle sort, ofcourse can't do Arrays.sort()! Should sort in one pass. +Also, we don't need to make each wiggle elements in ascending order (1,(4),2,(5),3,(6) ... etc). I thought it over. +---- +List out the example of 1,2,3,4,5,6,7,8, want to move (5,6,7,8) and insert between (1,2,3,4). It follows the follows patter: +Assume total length = n, and we are moving index i = (1 ~ n) +Step1: swap (n + i)/2, and i, (where initially i == 1) +Step2: swap (n + i)/2, and i+1 +Step2: i+=2; + + +public class Solution { + public void wiggleSort(int[] nums) { + if (nums == null || nums.length == 0) { + return; + } + Arrays.sort(nums); + if (nums.length <= 2) { + return; + } + int leng = nums.length; + int ind1 = 0; + int ind2 = 0 + for (int i = 1; i < leng; i++) { + //Step1 + ind1 = (leng + i) / 2; + ind2 = i; + swap(ind1, ind2); + //Step2: + ind2 = i + 1; + swap(ind1, ind2); + } + } + + public void swap(int[] nums, int x, int y) { + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } +} +*/ + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Word Pattern.java b/Others/old records/LeetCode-Merged/Java/Word Pattern.java new file mode 100644 index 0000000..fa8d176 --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Word Pattern.java @@ -0,0 +1,69 @@ +每个char代表一个pattern。用HashMap. +但不够,如果a也match dog, b也match dog, 纠错了。比如pattern = "abba", str = "dog dog dog dog"。 +因此第二个HashMap 反过来。 +确保pattern和str一一对应。 +``` +/* +Given a pattern and a string str, find if str follows the same pattern. + +Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str. + +Examples: +pattern = "abba", str = "dog cat cat dog" should return true. +pattern = "abba", str = "dog cat cat fish" should return false. +pattern = "aaaa", str = "dog cat cat dog" should return false. +pattern = "abba", str = "dog dog dog dog" should return false. +Notes: +You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space. + +Credits: +Special thanks to @minglotus6 for adding this problem and creating all test cases. + +Hide Company Tags Dropbox +Hide Tags Hash Table +Hide Similar Problems (E) Isomorphic Strings (H) Word Pattern II + +*/ + +/* +Thoughts: +2 HashMap, HashMap double check +*/ +public class Solution { + public boolean wordPattern(String pattern, String str) { + if (pattern != null && str != null && pattern.length() == 0 && str.length() == 0) { + return true; + } + if (pattern == null || pattern.length() == 0 || str == null || str.length() == 0) { + return false; + } + String[] strArr = str.split(" "); + if (pattern.length() != strArr.length) { + return false; + } + + HashMap map = new HashMap(); + HashMap mapStr = new HashMap(); + + for (int i = 0; i < strArr.length; i++){ + if (!map.containsKey(pattern.charAt(i))) { + map.put(pattern.charAt(i), strArr[i]); + } else { + if (!map.get(pattern.charAt(i)).equals(strArr[i])) { + return false; + } + } + if (!mapStr.containsKey(strArr[i])) { + mapStr.put(strArr[i], pattern.charAt(i)); + } else { + if (mapStr.get(strArr[i]) != pattern.charAt(i)) { + return false; + } + } + } + return true; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/Zigzag Iterator.java b/Others/old records/LeetCode-Merged/Java/Zigzag Iterator.java new file mode 100644 index 0000000..e0d02fd --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/Zigzag Iterator.java @@ -0,0 +1,90 @@ +这个题目相对简单. 做的时候我先考虑起来k条怎么办. 那么用个map把index和每个listmark一下就好了。 +每次next(), 相应的list的头拿下来就好。 +然后就跑圈呗,每次刷一个list头。不难。只要把几个variable维护清楚就行。 +``` +/* +Given two 1d vectors, implement an iterator to return their elements alternately. + +For example, given two 1d vectors: + +v1 = [1, 2] +v2 = [3, 4, 5, 6] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1, 3, 2, 4, 5, 6]. + +Follow up: What if you are given k 1d vectors? How well can your code be extended to such cases? + +Clarification for the follow up question - Update (2015-09-18): +The "Zigzag" order is not clearly defined and is ambiguous for k > 2 cases. If "Zigzag" does not look right to you, replace "Zigzag" with "Cyclic". For example, given the following input: + +[1,2,3] +[4,5,6,7] +[8,9] +It should return [1,4,8,2,5,9,3,6,7]. + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Flatten 2D Vector, (M) Peeking Iterator + +*/ + +/* +Thoughts: +HashMap +alter the index to pick correct list +maintain a total size variable. +hashNext: size > 0? +next(): while(map.get(index).length() == 0) : find next list. +return list.get(0), also list.remove(0) + +Note: be careful with all the size, length, index. size does not change once fixed. Remember in next(): index++ and length--; +*/ +public class ZigzagIterator { + private HashMap> map; + private int length = 0; + private int size = 0; + private int index = 0; + public ZigzagIterator(List v1, List v2) { + map = new HashMap>(); + if (v1 != null && v1.size() > 0) { + map.put(size, v1); + length += v1.size(); + size++; + } + if (v2 != null && v2.size() > 0) { + map.put(size, v2); + length += v2.size(); + size++; + } + if (length == 0) { + return; + } + } + + public int next() { + while(map.get(index).size() == 0) { + index++; + if (index == size) { + index = 0; + } + } + int rst = map.get(index).get(0); + map.get(index).remove(0); + length--; + index++; + if (index == size) { + index = 0; + } + return rst; + } + + public boolean hasNext() { + return length > 0; + } +} + + +/** + * Your ZigzagIterator object will be instantiated and called as such: + * ZigzagIterator i = new ZigzagIterator(v1, v2); + * while (i.hasNext()) v[f()] = i.next(); + */ +``` \ No newline at end of file diff --git a/Others/old records/LeetCode-Merged/Java/reverseInteger.java b/Others/old records/LeetCode-Merged/Java/reverseInteger.java new file mode 100644 index 0000000..22df33d --- /dev/null +++ b/Others/old records/LeetCode-Merged/Java/reverseInteger.java @@ -0,0 +1,35 @@ +/* +Reverse Integer + +Reverse digits of an integer. + +Example1: x = 123, return 321 +Example2: x = -123, return -321 +//input = 1534236469 + +Thinking process: +Make sure of operators. +Note: check for overflow using long. When integer is > Integer.MAX_VALUE, then it's overflow. +Initialize long : long x = 1234L; +Convert using (int) + +*/ +public class Solution { + public int reverse(int x) { + if (x == 0) { + return x; //123 + } + boolean sign = x > 0; //sign = true + long rst = 0L; + x = Math.abs(x); // 123 + while (x != 0) { //x = 123, 12, 1 + rst = rst * 10 + x % 10; //rst = 3, 30 + 2 = 32, 320 + 1 = 321 + x = x / 10; //x = 12; 1; 0 + } + if (rst < 0 || rst > Integer.MAX_VALUE) { + return 0; + } + return sign ? (int)rst : -(int)rst; + } +} + diff --git a/Others/old records/LeetCode-Merged/README.md b/Others/old records/LeetCode-Merged/README.md new file mode 100644 index 0000000..f56befe --- /dev/null +++ b/Others/old records/LeetCode-Merged/README.md @@ -0,0 +1,94 @@ +# LeetCode + +To host Java Solutions to problems from LeetCode(https://leetcode.com/problemset/algorithms/). +I Will try to revise the solutions once new problem or new testing case occurs. +Since I do not run .java files, they are formatted with markdowns to help compressing code in blog format. + +| Squence | Problem | Level | Language | +|:-------:|:--------------|:---------------|:---------:| +|0|[3Sum Smaller.java](https://github.com/shawnfan/LeetCode/blob/master/Java/3Sum Smaller.java)| |Java| +|1|[3Sum.java](https://github.com/shawnfan/LeetCode/blob/master/Java/3Sum.java)| |Java| +|2|[Alien Dictionary.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Alien Dictionary.java)| |Java| +|3|[Binary Search Tree Iterator.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Search Tree Iterator.java)| |Java| +|4|[Binary Tree Inorder Traversal.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Tree Inorder Traversal.java)| |Java| +|5|[Binary Tree Level Order Traversal.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Tree Level Order Traversal.java)| |Java| +|6|[Binary Tree Longest Consecutive Sequence.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Tree Longest Consecutive Sequence.java)| |Java| +|7|[Binary Tree Paths.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Tree Paths.java)| |Java| +|8|[Binary Tree Right Side View.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Binary Tree Right Side View.java)| |Java| +|9|[Building Outline.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Building Outline.java)| |Java| +|10|[Burst Balloons.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Burst Balloons.java)| |Java| +|11|[Closest Binary Search Tree Value.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Closest Binary Search Tree Value.java)| |Java| +|12|[Count Primes.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Count Primes.java)| |Java| +|13|[Course Schedule II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Course Schedule II.java)| |Java| +|14|[Course Schedule.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Course Schedule.java)| |Java| +|15|[Encode and Decode Strings.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Encode and Decode Strings.java)| |Java| +|16|[Excel Sheet Column Number.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Excel Sheet Column Number.java)| |Java| +|17|[ExcelSheetColumnNumber .java](https://github.com/shawnfan/LeetCode/blob/master/Java/ExcelSheetColumnNumber .java)| |Java| +|18|[Find Peak Element.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Find Peak Element.java)| |Java| +|19|[First Bad Version.java](https://github.com/shawnfan/LeetCode/blob/master/Java/First Bad Version.java)| |Java| +|20|[Flatten 2D Vector.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Flatten 2D Vector.java)| |Java| +|21|[Flattern 2D Vector.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Flattern 2D Vector.java)| |Java| +|22|[Flip Game II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Flip Game II.java)| |Java| +|23|[Flip Game.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Flip Game.java)| |Java| +|24|[Fraction to Recurring Decimal.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Fraction to Recurring Decimal.java)| |Java| +|25|[Game of Life.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Game of Life.java)| |Java| +|26|[Generate Parentheses.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Generate Parentheses.java)| |Java| +|27|[Graph Valid Tree.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Graph Valid Tree.java)| |Java| +|28|[Gray Code.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Gray Code.java)| |Java| +|29|[Group Anagrams.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Group Anagrams.java)| |Java| +|30|[H-Index II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/H-Index II.java)| |Java| +|31|[H-Index.java](https://github.com/shawnfan/LeetCode/blob/master/Java/H-Index.java)| |Java| +|32|[Implement strStr().java](https://github.com/shawnfan/LeetCode/blob/master/Java/Implement strStr().java)| |Java| +|33|[Implement Trie (Prefix Tree).java](https://github.com/shawnfan/LeetCode/blob/master/Java/Implement Trie (Prefix Tree).java)| |Java| +|34|[Insert Interval.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Insert Interval.java)| |Java| +|35|[Integer to English Words.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Integer to English Words.java)| |Java| +|36|[Intersection of Two Linked Lists.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Intersection of Two Linked Lists.java)| |Java| +|37|[Jump Game.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Jump Game.java)| |Java| +|38|[Kth Smallest Element in a BST.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Kth Smallest Element in a BST.java)| |Java| +|39|[Letter Combinations of a Phone Number.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Letter Combinations of a Phone Number.java)| |Java| +|40|[Longest Palindromic Substring.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Longest Palindromic Substring.java)| |Java| +|41|[Lowest Common Ancestor of a Binary Search Tree.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Lowest Common Ancestor of a Binary Search Tree.java)| |Java| +|42|[LRU Cache.java](https://github.com/shawnfan/LeetCode/blob/master/Java/LRU Cache.java)| |Java| +|43|[MaximumSubarray.java](https://github.com/shawnfan/LeetCode/blob/master/Java/MaximumSubarray.java)| |Java| +|44|[Median of Two Sorted Arrays.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Median of Two Sorted Arrays.java)| |Java| +|45|[Meeting Rooms II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Meeting Rooms II.java)| |Java| +|46|[Meeting Rooms.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Meeting Rooms.java)| |Java| +|47|[Merge Intervals.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Merge Intervals.java)| |Java| +|48|[Merge k Sorted Lists.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Merge k Sorted Lists.java)| |Java| +|49|[Merge Two Sorted Lists.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Merge Two Sorted Lists.java)| |Java| +|50|[Min Stack.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Min Stack.java)| |Java| +|51|[Minimum Height Trees.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Minimum Height Trees.java)| |Java| +|52|[Missing Ranges.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Missing Ranges.java)| |Java| +|53|[Multiply Strings.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Multiply Strings.java)| |Java| +|54|[Number of Islands.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Number of Islands.java)| |Java| +|55|[One Edit Distance.java](https://github.com/shawnfan/LeetCode/blob/master/Java/One Edit Distance.java)| |Java| +|56|[Paint Fence.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Paint Fence.java)| |Java| +|57|[Palindrome Permutation.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Palindrome Permutation.java)| |Java| +|58|[Peeking Iterator.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Peeking Iterator.java)| |Java| +|59|[Perfect Squares.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Perfect Squares.java)| |Java| +|60|[Plus One.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Plus One.java)| |Java| +|61|[Restore IP Addresses.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Restore IP Addresses.java)| |Java| +|62|[Reverse Linked List.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Reverse Linked List.java)| |Java| +|63|[Reverse Words in a String II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Reverse Words in a String II.java)| |Java| +|64|[reverseInteger.java](https://github.com/shawnfan/LeetCode/blob/master/Java/reverseInteger.java)| |Java| +|65|[Rotate Image.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Rotate Image.java)| |Java| +|66|[Search a 2D Matrix II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Search a 2D Matrix II.java)| |Java| +|67|[Search a 2D Matrix.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Search a 2D Matrix.java)| |Java| +|68|[String to Integer.java](https://github.com/shawnfan/LeetCode/blob/master/Java/String to Integer.java)| |Java| +|69|[Strobogrammatic Number II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Strobogrammatic Number II.java)| |Java| +|70|[Strobogrammatic Number.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Strobogrammatic Number.java)| |Java| +|71|[Summary Ranges.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Summary Ranges.java)| |Java| +|72|[Surrounded Regions.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Surrounded Regions.java)| |Java| +|73|[Symmetric Binar Tree.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Symmetric Binar Tree.java)| |Java| +|74|[Trapping Rain Water.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Trapping Rain Water.java)| |Java| +|75|[Two Sum II - Input array is sorted.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Two Sum II - Input array is sorted.java)| |Java| +|76|[Two Sum.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Two Sum.java)| |Java| +|77|[Ugly Number II.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Ugly Number II.java)| |Java| +|78|[Ugly Number.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Ugly Number.java)| |Java| +|79|[Unique Word Abbreviation.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Unique Word Abbreviation.java)| |Java| +|80|[Valid Anagram.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Valid Anagram.java)| |Java| +|81|[Valid Parentheses.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Valid Parentheses.java)| |Java| +|82|[Validate Binary Search Tree.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Validate Binary Search Tree.java)| |Java| +|83|[Wiggle Sort.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Wiggle Sort.java)| |Java| +|84|[Word Pattern.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Word Pattern.java)| |Java| +|85|[Zigzag Iterator.java](https://github.com/shawnfan/LeetCode/blob/master/Java/Zigzag Iterator.java)| |Java| diff --git a/Others/old records/LeetCode-Merged/WordPress.txt b/Others/old records/LeetCode-Merged/WordPress.txt new file mode 100644 index 0000000..dd1c56f --- /dev/null +++ b/Others/old records/LeetCode-Merged/WordPress.txt @@ -0,0 +1,2 @@ +Java Solutions to problems from LeetCode(https://leetcode.com/problemset/algorithms/). +
#Problem      Level  Language
03Sum Smaller.javaJava
13Sum.javaJava
2Alien Dictionary.javaJava
3Binary Search Tree Iterator.javaJava
4Binary Tree Inorder Traversal.javaJava
5Binary Tree Level Order Traversal.javaJava
6Binary Tree Longest Consecutive Sequence.javaJava
7Binary Tree Paths.javaJava
8Binary Tree Right Side View.javaJava
9Building Outline.javaJava
10Burst Balloons.javaJava
11Closest Binary Search Tree Value.javaJava
12Count Primes.javaJava
13Course Schedule II.javaJava
14Course Schedule.javaJava
15Encode and Decode Strings.javaJava
16Excel Sheet Column Number.javaJava
17ExcelSheetColumnNumber .javaJava
18Find Peak Element.javaJava
19First Bad Version.javaJava
20Flatten 2D Vector.javaJava
21Flattern 2D Vector.javaJava
22Flip Game II.javaJava
23Flip Game.javaJava
24Fraction to Recurring Decimal.javaJava
25Game of Life.javaJava
26Generate Parentheses.javaJava
27Graph Valid Tree.javaJava
28Gray Code.javaJava
29Group Anagrams.javaJava
30H-Index II.javaJava
31H-Index.javaJava
32Implement strStr().javaJava
33Implement Trie (Prefix Tree).javaJava
34Insert Interval.javaJava
35Integer to English Words.javaJava
36Intersection of Two Linked Lists.javaJava
37Jump Game.javaJava
38Kth Smallest Element in a BST.javaJava
39Letter Combinations of a Phone Number.javaJava
40Longest Palindromic Substring.javaJava
41Lowest Common Ancestor of a Binary Search Tree.javaJava
42LRU Cache.javaJava
43MaximumSubarray.javaJava
44Median of Two Sorted Arrays.javaJava
45Meeting Rooms II.javaJava
46Meeting Rooms.javaJava
47Merge Intervals.javaJava
48Merge k Sorted Lists.javaJava
49Merge Two Sorted Lists.javaJava
50Min Stack.javaJava
51Minimum Height Trees.javaJava
52Missing Ranges.javaJava
53Multiply Strings.javaJava
54Number of Islands.javaJava
55One Edit Distance.javaJava
56Paint Fence.javaJava
57Palindrome Permutation.javaJava
58Peeking Iterator.javaJava
59Perfect Squares.javaJava
60Plus One.javaJava
61Restore IP Addresses.javaJava
62Reverse Linked List.javaJava
63Reverse Words in a String II.javaJava
64reverseInteger.javaJava
65Rotate Image.javaJava
66Search a 2D Matrix II.javaJava
67Search a 2D Matrix.javaJava
68String to Integer.javaJava
69Strobogrammatic Number II.javaJava
70Strobogrammatic Number.javaJava
71Summary Ranges.javaJava
72Surrounded Regions.javaJava
73Symmetric Binar Tree.javaJava
74Trapping Rain Water.javaJava
75Two Sum II - Input array is sorted.javaJava
76Two Sum.javaJava
77Ugly Number II.javaJava
78Ugly Number.javaJava
79Unique Word Abbreviation.javaJava
80Valid Anagram.javaJava
81Valid Parentheses.javaJava
82Validate Binary Search Tree.javaJava
83Wiggle Sort.javaJava
84Word Pattern.javaJava
85Zigzag Iterator.javaJava
\ No newline at end of file diff --git a/Others/old records/LintCode-Backup/2 Sum.java b/Others/old records/LintCode-Backup/2 Sum.java new file mode 100644 index 0000000..e924d2c --- /dev/null +++ b/Others/old records/LintCode-Backup/2 Sum.java @@ -0,0 +1,126 @@ +M + +解法1:相对暴力简洁, HashMap,找到一个value, 存一个; 若在HashMap里面 match 到结果, 就return HashMap里存的index. O(n) space && time. + +解法2:Sort array, two pointer 前后++,--搜索。Sort 用时O(nlogn). + 1. 第一步 two pointer 找 value. + 2. 注意,要利用额外的空间保留original array, 用来时候找index. (此处不能用HashMap,因为以value 为key,但value可能重复) + O(n) space, O(nlogn) time. + + +``` + +/* +Given an array of integers, find two numbers such that they add up to a specific target number. +The function twoSum should return indices of the two numbers such that they add up to the target, +where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are NOT zero-based. +Example +numbers=[2, 7, 11, 15], target=9 +return [1, 2] +Note +You may assume that each input would have exactly one solution +Challenge +Either of the following solutions are acceptable: +O(n) Space, O(nlogn) Time +O(n) Space, O(n) Time +Tags Expand +Two Pointers Sort Hash Table Array Airbnb Facebook +*/ + +/* +Thoughts: + Using a HashMap, O(n) space and O(n) time. + Thinking process: + Push everything into a HashMap. + Check if one element exist in the HashMap, if so save it. Meanwhile, save the other one. + Trick: after adding into the HashMap, we are looking for the 2nd index first. + Always check (target - current) from the HashMap. + If exist, that means index0 has already been pushed into the HashMap and current value is at index1. + (key, value) = (numbers[i], i) + Note: return index+1 because this is not 0-based. +*/ + +public class Solution { + //Using HashMap + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length == 0) { + return null; + } + int[] rst = new int[2]; + HashMap map = new HashMap(); + for (int i = 0; i < numbers.length; i++) { + if (map.containsKey(target - numbers[i])) { + rst[0] = map.get(target - numbers[i]) + 1; + rst[1] = i + 1; + } else { + map.put(numbers[i], i); + } + } + return rst; + } +} + + + +//2. O(n) Space O(nlogn) time +/* + Feels like binary search when looking at O(nlogn) + 1. sort + 2. loop all number + 3. binary search on rest +*/ +public class Solution { + public int[] twoSum(int[] numbers, int target) { + if (numbers == null || numbers.length == 0) { + return null; + } + int[] original = new int[numbers.length]; + for (int i = 0; i < numbers.length; i++) { + original[i] = numbers[i]; + } + + Arrays.sort(numbers); + int start = 0; + int end = numbers.length - 1; + int num1 = -1; + int num2 = -1; + while (start != end) { + int sum = numbers[start] + numbers[end]; + if (sum == target) { + num1 = numbers[start]; + num2 = numbers[end]; + break; + }else if (sum < target) { + start++; + } else { + end--; + } + } + + //Find the num1,num2 in original array and record the index + int[] rst = new int[2]; + rst[0] = -1; + rst[1] = -1; + for (int i = 0; i < original.length; i++) { + if (original[i] == num1 || original[i] == num2) { + if (rst[0] == -1) { + rst[0] = i + 1; + } else { + rst[1] = i + 1; + break; + } + } + } + return rst; + } +} + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/3 Sum Closest.java b/Others/old records/LintCode-Backup/3 Sum Closest.java new file mode 100644 index 0000000..da399e9 --- /dev/null +++ b/Others/old records/LintCode-Backup/3 Sum Closest.java @@ -0,0 +1,57 @@ +M + +3Sum 的一种简单形式, 并且都没有找index, value, 而只是找个sum罢了. + +double for loop。 2Sum只能用土办法 left/right 2 pointers。 O(n^2) + +注意:check closest时候用long, 以免int不够用 + +``` +/* +Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. +Note +You may assume that each input would have exactly one solution. +Example +For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). +Tags Expand +Two Pointers Sort Array + +*/ + +/* +Thoughts: + Similar to 3 SUM. + Starting from the left-element, assume it's the solution. Move the 2 pointers in the right-side-array. + Using the two pointers, trying to find ele1 + ele2 + ele3 = closest number to target. + Note: for comparing closet, use initial value Integer.MAX_VALUE. Be aware of the overflow of integer, use long to handle. + +*/ +public class Solution { + + public int threeSumClosest(int[] num, int target) { + if (num == null || num.length < 3) { + return Integer.MAX_VALUE; + } + Arrays.sort(num); + long closest = (long) Integer.MAX_VALUE; + for (int i = 0; i < num.length - 2; i++) { + int left = i + 1; + int right = num.length - 1; + while (left < right) { + int sum = num[i] + num[left] + num[right]; + if (sum == target) { + return sum; + } else if (sum < target) { + left++; + } else { + right--; + } + closest = Math.abs(sum - target) < Math.abs(closest - target) + ? (long) sum : closest; + }//while + }//for + return (int) closest; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/3 Sum.java b/Others/old records/LintCode-Backup/3 Sum.java new file mode 100644 index 0000000..ec2c9b9 --- /dev/null +++ b/Others/old records/LintCode-Backup/3 Sum.java @@ -0,0 +1,148 @@ +M + +用个for loop 加上 2sum 的土办法。 + +注意: + 1. 找 value triplets, 多个结果。注意,并非找index。 + 2. 要升序, 第一层for loop 从最后一个元素挑起, 保证了顺序。 + 3. 去掉duplicate: check用过的同样的数字,都跳掉。不需要用同样的数字再计算一边已有结果。 + +步骤: + 1. For loop 挑个数字A. + 2. 2Sum 出一堆2个数字的结果 + 3. Cross match 步骤1里面的A. + +时间 O(n^2), 两个nested loop + + +另外, 还是可以用HashMap来做2Sum。稍微短点。还是要注意handle duplicates. + + +``` +/* +Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? +Find all unique triplets in the array which gives the sum of zero. + +Example +For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: + +(-1, 0, 1) +(-1, -1, 2) +Note +Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c) + +The solution set must not contain duplicate triplets. + +Tags Expand +Two Pointers Sort Array Facebook +*/ + +/* +Thoughts: + Remember to check for null and edge-soluton. + Before everything, Arrays.sort() the given array, in order to effectively handle the duplicates. + At 3SUM level, takes 1 element out and do 2SUM on the rest of the front elements of the array. Note, 2SUM has multitple solutions (need to handle duplicates) + Cross-match the 2SUM solution with the selected element from 3SUM level. +*/ + +public class Solution { + public ArrayList> threeSum(int[] numbers) { + ArrayList> rst = new ArrayList>(); + if (numbers == null && numbers.length <= 2) {// Length at least >= 3 + return rst; + } + Arrays.sort(numbers);//Sort in order to handle duplicates + for (int i = numbers.length - 1; i >= 2; i--) {// i >=2 because at least 3 element in result; starting from end, ensures non-descending order + if (i < numbers.length - 1 && numbers[i] == numbers[i + 1]) { + continue;//The case of numbers[i + 1]: should have already covered all possibilities of the case numbers[i], so safe to skip + } + ArrayList> twoSum = calTwoSum(numbers, i - 1, 0 - numbers[i]);//Pick the 3rd element numbers[i] + for (int j = 0; j < twoSum.size(); j++) {//Find two sum of rest-front elements. Cross add them with numbers[i] + twoSum.get(j).add(numbers[i]); + } + rst.addAll(twoSum); + } + return rst; + } + //Two Sum. Multiple answer + public ArrayList> calTwoSum(int[] num, int end, int target) { + ArrayList> rst = new ArrayList>(); + int left = 0; + int right = end; + while (left < right) { + if (num[left] + num[right] == target) { + ArrayList match = new ArrayList(); + match.add(num[left]); + match.add(num[right]); + rst.add(match); + left++; + right--; + //For unique number A, there is only 1 unique number B such that A + B == target. + //Therefore, once found the match, erase all numbers that's equal to A or equal to B + while (left < right && num[left] == num[left - 1]) { + left++; + } + while (left < right && num[right] == num[right + 1]) { + right--; + } + } else if (num[left] + num[right] < target) {//Since int[] num is sorted: move L to right-side to get larger value. + left++; + } else { + right--; + } + } + return rst; + } +} + + +/* + Thoughts: + Exact same approach, except using HashMap in 2Sum +*/ +//With HashMap 2Sum +public class Solution { + public ArrayList> threeSum(int[] numbers) { + ArrayList> rst = new ArrayList>(); + if (numbers == null && numbers.length <= 2) {// Length at least >= 3 + return rst; + } + Arrays.sort(numbers);//Sort in order to handle duplicates + for (int i = numbers.length - 1; i >= 2; i--) {// i >=2 because at least 3 element in result; starting from end, ensures non-descending order + if (i < numbers.length - 1 && numbers[i] == numbers[i + 1]) { + continue;//The case of numbers[i + 1]: should have already covered all possibilities of the case numbers[i], so safe to skip + } + ArrayList> twoSum = calTwoSum(numbers, i - 1, 0 - numbers[i]);//Pick the 3rd element numbers[i] + for (int j = 0; j < twoSum.size(); j++) {//Find two sum of rest-front elements. Cross add them with numbers[i] + twoSum.get(j).add(numbers[i]); + } + rst.addAll(twoSum); + } + return rst; + } + //Two Sum. Multiple answer, with HashMap + public ArrayList> calTwoSum(int[] num, int end, int target) { + ArrayList> rst = new ArrayList>(); + ArrayList match; + HashMap map = new HashMap(); + for (int i = 0; i <= end; i++) { + if (map.containsKey(num[i])) { + match = new ArrayList(); + match.add(num[map.get(num[i])]); + match.add(num[i]); + if (!rst.contains(match)) { + rst.add(new ArrayList(match)); + } + } else { + map.put(target - num[i], i); + } + //Skip duplicate + if (i < end && num[i] == num[i + 1]) { + continue; + } + } + return rst; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/4 Sum.java b/Others/old records/LintCode-Backup/4 Sum.java new file mode 100644 index 0000000..f8fee31 --- /dev/null +++ b/Others/old records/LintCode-Backup/4 Sum.java @@ -0,0 +1,230 @@ +M + +方法1: 3Sum外面再加一层. 参考3Sum. 时间O(n^3)。 但此方法在k-sum时候,无疑过于费时间. O(n^k) + +方法2: 参见 http://lifexplorer.me/leetcode-3sum-4sum-and-k-sum/ + 1. 利用2Sum的原理,把4Sum分为连个2Sum。左一个pair,右一个pair,每个pair里面放2个数字。 + 2. 以一个点,i,作为分界口,也要列举出所有i之前的pair,作为基础。 + 3. 再尝试从所有i+1后面,找合适的2nd pair。 + + 注意:在造class Pair时候,要做@override的function: hashCode(), equals(Object d). 平时不太想得起来用。 + +``` +/* +Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? + +Find all unique quadruplets in the array which gives the sum of target. + +Example +Given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: + +(-1, 0, 0, 1) +(-2, -1, 1, 2) +(-2, 0, 0, 2) +Note +Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d) +The solution set must not contain duplicate quadruplets. + +Tags Expand +Two Pointers Sort Hash Table Array + +*/ + +/* +Thoughts +Perform another layer outside of 3SUM. O(n^3). +Note: If try to divide and perform two 2SUM, it will be a bit difficult. Refer to http://blog.csdn.net/linhuanmars/article/details/24826871 + +*/ +public class Solution { + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if(numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + //Pick 1st element + for (int i = 0; i < numbers.length - 3; i++) { + if (i != 0 && numbers[i] == numbers[i - 1]) {//Check for duplicate of 1st element + continue; + } + //Pick 2nd element + for (int j = i + 1; j < numbers.length - 2; j++) { + if (j != i + 1 && numbers[j] == numbers[j - 1]) {//Check for duplicate of 2nd element + continue; + } + //Pick 3rd and 4th element + int third = j + 1; + int fourth = numbers.length - 1; + while (third < fourth) { + int sum = numbers[i] + numbers[j] + numbers[third] + numbers[fourth]; + if (sum < target) { + third++; + } else if (sum > target) { + fourth--; + } else {//sum == target + ArrayList list = new ArrayList(); + list.add(numbers[i]); + list.add(numbers[j]); + list.add(numbers[third]); + list.add(numbers[fourth]); + rst.add(list); + third++; + fourth--; + while (third < fourth && numbers[third] == numbers[third - 1]) { + third++; + } + while (third < fourth && numbers[fourth] == numbers[fourth + 1]){ + fourth--; + } + } + } + } + } + return rst; + } +} + + +/* +NOT Complete yet. Has a order issue in HashSet +http://lifexplorer.me/leetcode-3sum-4sum-and-k-sum/ +Thoughts: +Utilize 2Sum. + +*/ + +public class Solution { + //Create class Pair for HashSet to use + class Pair { + Integer x; + Integer y; + + public Pair(int x, int y){ + this.x = x; + this.y = y; + } + + @Override + public int hashCode(){ + return this.x.hashCode() + this.y.hashCode(); + } + + @Override + public boolean equals(Object d) { + if (!(d instanceof Pair)) { + return false; + } + Pair p = (Pair)d; + return (this.x == p.x) && (this.y == p.y); + } + } + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if (numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + HashMap> map = new HashMap>(); + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) { + int sum = numbers[i] + numbers[j]; + if (map.containsKey(target - sum)) { + for (Pair p : map.get(target - sum)) { + ArrayList list = new ArrayList(); + list.add(p.x); + list.add(p.y); + list.add(numbers[i]); + list.add(numbers[j]); + if (!rst.contains(list)) { + rst.add(list); + } + } + } + } + //Add all pairs up to i + for (int j = 0; j < i; j++) { + int sum = numbers[i] + numbers[j]; + if (!map.containsKey(sum)) { + map.put(sum, new HashSet()); + } + map.get(sum).add(new Pair(numbers[j], numbers[i])); + } + } + + return rst; + } + +} + + + +public class Solution { + //Create class Pair for HashSet to use + class Pair { + Integer x; + Integer y; + + public Pair(int x, int y){ + this.x = x; + this.y = y; + } + + @Override + public int hashCode(){ + return this.x.hashCode() + this.y.hashCode(); + } + + @Override + public boolean equals(Object d) { + if (!(d instanceof Pair)) { + return false; + } + Pair p = (Pair)d; + return (this.x == p.x) && (this.y == p.y); + } + } + + public ArrayList> fourSum(int[] numbers, int target) { + ArrayList> rst = new ArrayList>(); + if (numbers == null || numbers.length < 4) { + return rst; + } + Arrays.sort(numbers); + HashMap> map = new HashMap>(); + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) { + int sum = numbers[i] + numbers[j]; + if (map.containsKey(target - sum)) { + for (Pair p : map.get(target - sum)) { + ArrayList list = new ArrayList(); + list.add(p.x); + list.add(p.y); + list.add(numbers[i]); + list.add(numbers[j]); + if (!rst.contains(list)) { + rst.add(list); + } + } + } + } + //Add all pairs up to i + for (int j = 0; j < i; j++) { + int sum = numbers[i] + numbers[j]; + if (!map.containsKey(sum)) { + map.put(sum, new ArrayList()); + } + map.get(sum).add(new Pair(numbers[j], numbers[i])); + } + } + + return rst; + } + +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/A+B.java b/Others/old records/LintCode-Backup/A+B.java new file mode 100644 index 0000000..63dab71 --- /dev/null +++ b/Others/old records/LintCode-Backup/A+B.java @@ -0,0 +1,52 @@ +E + +Bit Operation + + a & b: 每bit可能出得余数 + a ^ b: 每bit在此次操作可能留下的值,XOR 操作 + 每次左移余数1位,然后存到b, 再去跟a做第一步。loop until b == 0 + + +``` +/* +Write a function that add two numbers A and B. You should not use + or any arithmetic operators. + +Example +Given a=1 and b=2 return 3 + +Note +There is no need to read data from standard input stream. Both parameters are given in function aplusb, you job is to calculate the sum and return it. + +Challenge +Of course you can just return a + b to get accepted. But Can you challenge not do it like that? + +Clarification +Are a and b both 32-bit integers? + +Yes. +Can I use bit operation? + +Sure you can. +Tags Expand +Cracking The Coding Interview Bit Manipulation + + +*/ + +/* +Thought: + Bit operation. Just to remmeber this problem, doing A+B using bit. +*/ +class Solution { + public int aplusb(int a, int b) { + while (b != 0) { + int carry = a & b; + a = a ^ b; + b = carry << 1; + } + return a; + } +}; + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Add Binary.java b/Others/old records/LintCode-Backup/Add Binary.java new file mode 100644 index 0000000..3bbd79f --- /dev/null +++ b/Others/old records/LintCode-Backup/Add Binary.java @@ -0,0 +1,90 @@ +E + +方法一:土办法没技术,把binary换成数字,加起来,再换成binary。如果input很大,那么很可能int,long都hold不住。不保险。 + +方法二:一般方法,string化为charArray,然后逐位加起,最后记得处理多余的一个carry on + + +``` +/* +Add Binary + +Given two binary strings, return their sum (also a binary string). + +Example +a = 11 + +b = 1 + +Return 100 + +Tags Expand +String Binary Facebook + + + +*/ + +/* +//Thougths: +1. Turn string binary format into integer +2. add integer +3. turn integer into binary string +Note: this just test if we know how to manipulate string/binary/Integer +*/ + +public class Solution { + /** + * @param a a number + * @param b a number + * @return the result + */ + public String addBinary(String a, String b) { + if (a == null || b == null || a.length() == 0 || b.length() == 0) { + return null; + } + int decimalA = Integer.parseInt(a, 2); + int decimalB = Integer.parseInt(b, 2); + + int sum = decimalA + decimalB; + + return Integer.toBinaryString(sum); + } +} + + + +/* + Thought: + Use binary property, add all and move carry-on + String to charArray +*/ + +public class Solution { + public String addBinary(String a, String b) { + if (a == null || b == null || a.length() == 0 || b.length() == 0) { + return null; + } + char[] shortArr = a.length() < b.length() ? a.toCharArray() : b.toCharArray(); + char[] longArr = a.length() < b.length() ? b.toCharArray() : a.toCharArray(); + int carry = 0; + int shortVal = 0; + int nextCarry = 0; + int diff = longArr.length - shortArr.length; + for (int i = longArr.length - 1; i >= 0; i--) { + shortVal = (i - diff) >= 0 ? shortArr[i - diff] - '0': 0; + nextCarry = (longArr[i] - '0' + shortVal + carry) / 2; + longArr[i] =(char)((longArr[i] - '0' + shortVal + carry) % 2 + '0'); + carry = nextCarry; + } + + if (carry != 0) { + return "1" + new String(longArr); + } + + return new String(longArr); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Add Two Numbers II.java b/Others/old records/LintCode-Backup/Add Two Numbers II.java new file mode 100644 index 0000000..5b3a138 --- /dev/null +++ b/Others/old records/LintCode-Backup/Add Two Numbers II.java @@ -0,0 +1,105 @@ +M + +LinkedList并没有反过来,那么自己反: + 方向相反。巧用stack. + +做加法都一样: + 1. carrier + 2. carrier = (rst + carrier) / 10 + 3. rst = (rst + carrier) % 10 + +``` +/* +You have two numbers represented by a linked list, where each node contains a single digit. +The digits are stored in forward order, such that the 1's digit is at the head of the list. +Write a function that adds the two numbers and returns the sum as a linked list. + +Example +Given 6->1->7 + 2->9->5. That is, 617 + 295. + +Return 9->1->2. That is, 912. + +Tags Expand +Linked List High Precision +*/ + +/* + Thoughts: Different from Add Two Numbers I, which is in reverse order. + 6 1 7 + 2 9 5 + 8 10 12 + +put the 2 linked list in 2 stacks. process the reversed list. +Save into another result stack. +At the end, return the actual order. +O(n) +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param l1: the first list + * @param l2: the second list + * @return: the sum list of l1 and l2 + */ + public ListNode addLists2(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } else if (l1 == null || l2 == null) { + return l1 == null ? l2 : l1; + } + + Stack result = new Stack(); + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + while (l1 != null) { + s1.push(l1); + l1 = l1.next; + } + + while (l2 != null) { + s2.push(l2); + l2 = l2.next; + } + + int carrier = 0; + while(!s1.isEmpty() || !s2.isEmpty()){ + int sum = 0; + if (!s1.isEmpty() && !s2.isEmpty()) { + sum += s1.pop().val + s2.pop().val; + } else if (!s1.isEmpty()) { + sum += s1.pop().val; + } else { + sum += s2.pop().val; + } + result.push(new ListNode((sum + carrier) % 10));//2, 1, 9 + carrier = (sum + carrier) / 10; // 12/10 = 1; 11/10 = 1; (8+1)/ 10 = 0 + } + if (carrier == 1) { + result.push(new ListNode(carrier)); + } + + //return results: + ListNode node = new ListNode(0); + ListNode dummy = node; + while (!result.isEmpty()) {//219 + node.next = result.pop(); + node = node.next; + } + + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Add Two Numbers.java b/Others/old records/LintCode-Backup/Add Two Numbers.java new file mode 100644 index 0000000..116250e --- /dev/null +++ b/Others/old records/LintCode-Backup/Add Two Numbers.java @@ -0,0 +1,73 @@ +E + +LinkedList都已经反转好了,直接做。 + +遍历两个l1,l2把carry-on处理好,每次生成一个新node,最后检查carry-on。 + +跟Add Binary的理解方式一模一样。 + + +``` +/* +You have two numbers represented by a linked list, +where each node contains a single digit. +The digits are stored in reverse order, +such that the 1's digit is at the head of the list. +Write a function that adds the two numbers and returns the sum as a linked list. + +Example +Given 7->1->6 + 5->9->2. That is, 617 + 295. + +Return 2->1->9. That is 912. + +Given 3->1->5 and 5->9->2, return 8->0->8. + +Tags Expand +Cracking The Coding Interview Linked List High Precision +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param l1: the first list + * @param l2: the second list + * @return: the sum list of l1 and l2 + */ + public ListNode addLists(ListNode l1, ListNode l2) { + ListNode rst = new ListNode(0); + ListNode dummy = rst; + int carrier = 0; + //while + while (l1 != null || l2 != null) { + if (l1 != null) { + carrier += l1.val; + l1 = l1.next; + } + if (l2 != null) { + carrier += l2.val; + l2 = l2.next; + } + rst.next = new ListNode(carrier % 10); + carrier = carrier / 10; + rst = rst.next; + } + //check the carrier + if (carrier == 1) { + rst.next = new ListNode(1); + } + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Add and Search Word.java b/Others/old records/LintCode-Backup/Add and Search Word.java new file mode 100644 index 0000000..693c4d5 --- /dev/null +++ b/Others/old records/LintCode-Backup/Add and Search Word.java @@ -0,0 +1,105 @@ +M + +Trie结构, prefix tree. +节点里面有char, isEnd, HashMap +记得怎么造trie:无增有移,没node就加,有node就移动。 +寻找word也一样逻辑:无错有移。 + + +``` +/* +Design a data structure that supports the following two operations: addWord(word) and search(word) + +search(word) can search a literal word or a regular expression string containing only letters a-z or .. + +A . means it can represent any one letter. + +Example +addWord("bad") +addWord("dad") +addWord("mad") +search("pad") // return false +search("bad") // return true +search(".ad") // return true +search("b..") // return true +Note +You may assume that all words are consist of lowercase letters a-z. + +Tags Expand +Trie +*/ + + +/* +Build the WordDictionary like a TrieTree. +Note: the '.' indicates any letter, which means we'd have to traverse through all possible letters in current level. +Only one of the returning search results needs to be true + +Note: +TrieNode contains that char, boolean, and HashMap of children +*/ + +public class WordDictionary { + class TrieNode{ + HashMap children; + boolean isEnd; + + public TrieNode() { + this.children = new HashMap(); + this.isEnd = false; + } + } + + TrieNode root; + public WordDictionary(){ + this.root = new TrieNode(); + } + + // Adds a word into the data structure. + public void addWord(String word) { + TrieNode node = root; + for (int i =0; i < word.length(); i++) { + char c = word.charAt(i); + if (!node.children.containsKey(c)) { + node.children.put(c, new TrieNode()); + } + node = node.children.get(c); + } + node.isEnd = true; + } + + // Returns if the word is in the data structure. A word could + // contain the dot character '.' to represent any one letter. + public boolean search(String word) { + return searchHelper(root, word, 0); + } + + public boolean searchHelper(TrieNode root, String word, int index) { + if (index == word.length()) { + return root.isEnd; + } + TrieNode node = root; + char c = word.charAt(index); + //border conditon: + if (node.children.containsKey(c)) { + return searchHelper(node.children.get(c), word, index + 1); + } else if (c == '.'){ + for (Map.Entry entry : node.children.entrySet()) { + if (searchHelper(entry.getValue(), word, index + 1)) { + return true; + } + } + return false; + } else { + return false; + } + } +} + +// Your WordDictionary object will be instantiated and called as such: +// WordDictionary wordDictionary = new WordDictionary(); +// wordDictionary.addWord("word"); +// wordDictionary.search("pattern"); + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Anagrams.java b/Others/old records/LintCode-Backup/Anagrams.java new file mode 100644 index 0000000..4b47340 --- /dev/null +++ b/Others/old records/LintCode-Backup/Anagrams.java @@ -0,0 +1,77 @@ +M + +HashMap 的做法. sort每个string, 存进HashMap, 重复的就是anagrams,最后输出。 + toCharArray + Arrays.sort + Stirng.valueOf(char[]) + +时间n*L*O(logL),L是最长string的长度。 + + + +另一种做法:http://www.jiuzhang.com/solutions/anagrams/ + 1. take each string, count the occurrance of the 26 letters. save in int[]count. + 2. hash the int[] count and output a unique hash value. + hash = hash * a + num + a = a * b. + 3. save to hashmap in the same way as we do. + +这一步把for s: strs 里面的时间复杂度降到了O(L). L = s.length(). +Need to work on the getHash() function. + +时间变成n*O(L). Better. + + +``` +/* +Given an array of strings, return all groups of strings that are anagrams. + +Example +Given ["lint", "intl", "inlt", "code"], return ["lint", "inlt", "intl"]. + +Given ["ab", "ba", "cd", "dc", "e"], return ["ab", "ba", "cd", "dc"]. + +Note +All inputs will be in lower-case + +Tags Expand +String Hash Table + + +*/ + +/* + + Recap 12.09.2015 + Feels like put into a hashmap of each string's sorted version. > + compare each string. If match, add into it. + reurn all that has >= 2 items +*/ +public class Solution { + public List anagrams(String[] strs) { + List rst = new ArrayList(); + if (strs == null || strs.length == 0) { + return rst; + } + HashMap> map = new HashMap>(); + for (int i = 0; i < strs.length; i++) { + char[] arr = strs[i].toCharArray(); + Arrays.sort(arr); + String s = String.valueOf(arr); + if (!map.containsKey(s)) { + ArrayList list = new ArrayList(); + map.put(s, list); + } + map.get(s).add(strs[i]); + } + //check instance occurs >= 2 + for (Map.Entry> entry : map.entrySet()) { + if (entry.getValue().size() >= 2) { + rst.addAll(entry.getValue()); + } + } + return rst; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Backpack II.java b/Others/old records/LintCode-Backup/Backpack II.java new file mode 100644 index 0000000..74f50ea --- /dev/null +++ b/Others/old records/LintCode-Backup/Backpack II.java @@ -0,0 +1,122 @@ +M + +做了Backpack I, 这个就如出一辙。 +想法还是,选了A[i-1] 或者没选A[i]. +一路往前跑不回头。就出来了。 +其实这个Backpack II 还更容易看懂代码。 + +O(m)的做法: +想想,的确我们只care 最后一行,所以一个存value的就够了。 +注意:和bakcpackI的 O(m)一样的,j是倒序的。如果没有更好的j,就不要更新。就是这个道理。 + + +``` +/* +Given n items with size Ai and value Vi, and a backpack with size m. +What's the maximum value can you put into the backpack? + + +Example +Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. +The maximum value is 9. + +Note +You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m. + +Challenge +O(n x m) memory is acceptable, can you do it in O(m) memory? + +Tags Expand +LintCode Copyright Dynamic Programming Backpack +*/ + + +/* + Thoughts: + In Backpack I, we store true/false to indicate the largest j in last dp row. + Here, we can store dp[i][j] == max value. + + State: + dp[i][j] : with i-1 items that fills exaclty size j, what's the max value + + Fn: + still, picked or did not picked A[i-1] + 1. Didn't pick. Value remains the same as if we didn't add A[i-1] + 2. Picked A[i - 1]. Hence, find out previous record dp[i-1][j - A[i - 1]], then add up the A[i-1] item's value V[i-1]. + 3. Compare 1, and 2 for max value. + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + V[i - 1]) + + Init: + dp[0][0] = 0; // 0 item, fills size 0, and of course value -> 0 + + Return: + dp[A.length][m] + + Note: + when creating dp, we do (A.length + 1) for row size, simply because we get used to checking A[i-1] for prevous record ... Just keep this style. Don't get confused. +*/ + + +public class Solution { + /** + * @param m: An integer m denotes the size of a backpack + * @param A & V: Given n items with size A[i] and value V[i] + * @return: The maximum value + */ + public int backPackII(int m, int[] A, int V[]) { + if (A == null || V == null || A.length == 0 || V.length == 0 || A.length != V.length || m <= 0) { + return 0; + } + int[][] dp = new int[A.length + 1][m + 1]; + dp[0][0] = 0; // 0 item, to make pack size = 0, of course value = 0. + + for (int i = 1; i <= A.length; i++) { + for (int j = 0; j <= m; j++) { + if (j - A[i - 1] >= 0) { + dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - A[i - 1]] + V[i - 1]); + } else { + dp[i][j] = dp[i - 1][j]; + } + } + } + + return dp[A.length][m]; + } +} + + +/* + To use just O(m) sapce. + Just like in Backpack I, at the end, we only care about the last row. + Why not just maintain a row, always keep the max value. + + Note: Only update dp[j] if adding A[i-1] would be greater than current dp[j] + + It's a bit hard to come up with this... but it's good exercise. +*/ + +public class Solution { + + public int backPackII(int m, int[] A, int V[]) { + if (A == null || V == null || A.length == 0 || V.length == 0 || A.length != V.length || m <= 0) { + return 0; + } + int[]dp = new int[m + 1]; + dp[0] = 0; // 0 item, to make pack size = 0, of course value = 0. + + for (int i = 1; i <= A.length; i++) { + for (int j = m; j >= 0; j--) { + if (j - A[i - 1] >= 0 && dp[j - A[i - 1]] + V[i - 1] > dp[j]) { + dp[j] = dp[j - A[i - 1]] + V[i - 1]; + } + } + } + + return dp[m]; + } +} + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Backpack.java b/Others/old records/LintCode-Backup/Backpack.java new file mode 100644 index 0000000..d2a8d92 --- /dev/null +++ b/Others/old records/LintCode-Backup/Backpack.java @@ -0,0 +1,140 @@ +M + +DP。 + row是item大小: 0, A[0], A[1] ... A[A.length -1] + col是背包累积的size: 0, 1, 2, ... m. + +想法: + dp[i][j]有这么i-1个item, 用他们可否组成size为j的背包?true/false. (反过来考虑了,不是想是否超过size j, 而是考虑是否能拼出exact size == j)。 + 注意注意:虽然dp里面一直存在i的位置,实际上考虑的是在i位置的时候,看前i-1个item. + +看一遍code,会发现: + 1. picked A[i-1]: 如果上一个item, A[i-1],被加了上来, 用j-A[i-1]看看,是否这再前一步也true. true就好啦。 + 2. did not pick A[i-1]: 那就是说,不加上A[i-1], 上一行d[i-1][j]还是需要是true。 + +最后: + 跑一边dp 最下面一个row. 从末尾开始找,最末尾的一个j (能让dp[i][j] == true)的,就是最多能装的大小 :) + +时间,空间都是:O(mn) + + + +再有: +O(m)时间的做法,具体看solution. 注意j是倒序的啊! +依然是O(mn)的空间 + + +``` +/* +Given n items with size Ai, an integer m denotes the size of a backpack. +How full you can fill this backpack? + +Example +If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select [2, 3, 5], +so that the max size we can fill this backpack is 10. +If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack. + +You function should return the max size we can fill in the given backpack. + +Note +You can not divide any item into small pieces. + +Challenge +O(n x m) time and O(m) memory. + +O(n x m) memory is also acceptable if you do not know how to optimize memory. + +Tags Expand +LintCode Copyright Dynamic Programming Backpack + + +*/ + +/* + Thoughts: Recap on 12.02.2015 + State + DP[i][j]: i is the index of Ai, and j is the size from (0 ~ m). + It means: depending if we added A[i-1], can we full-fill j-space? Return ture/false. + Note: that is, even j == 0, and I have a item with size == 0. There is nothing to add, which means the backpack can reach j == 0. True. + However, if we have a item with size == 2, but I need to fill space == 1. + I will either pick/not pick item of size 2; either way, can't fill a backpack with size 1. False; + Function: + DP[i][j] = DP[i - 1][j] || DP[i - 1][j - A[i - 1]]; // based on if previous value is true/false: 1. didn't really add A[i-1] || 2. added A[i-1]. + Init: + DP[0][0] = true; // 0 space and 0 items, true. + All the rest are false; + + Return the very last j that makes dp[A.length][j] true. +*/ + +public class Solution { + public int backPack(int m, int[] A) { + if (A == null || A.length == 0 || m <= 0) { + return 0; + } + boolean[][] dp = new boolean[A.length + 1][m + 1]; + dp[0][0] = true; + + for (int i = 1; i <= A.length; i++) { + for (int j = 0; j <= m; j++) { + //j is large enough: + if (j - A[i - 1] >= 0) { + //not added A[i - 1] or added A[i - 1] + dp[i][j] = dp[i - 1][j] || dp[i - 1][j - A[i - 1]]; + } else {// j not large enough, ofcourse not adding A[i-1] + dp[i][j] = dp[i - 1][j]; + } + } + } + //Largest possible size with dp[j] == true + for (int j = m; j >= 0; j--) { + if (dp[A.length][j]) { + return j; + } + } + return 0; + } +} + + + +/* +1D array: memory mxn, space m. Tricky tho ... + +Looking at the 2D version, we are really just checking the DP with fixed i=A.length. + +DP[j]: can we fit i items into j? +DP[j] == false || DP[j - A[i - 1]]. +Similar two cases: +1. Can't fit in, set false; +2. Can fit in, then just return if (j - A[i - 1]) works + +Core difference: only set the DP[j] when (j - A[i - 1] >= 0 && DP[j - A[i - 1]]): since we are running from m ~ 0, we don't want to override some existing values +*/ + +public class Solution { + public int backPack(int m, int[] A) { + if (A == null || m == 0) { + return 0; + } + + boolean[] DP = new boolean[m + 1]; + DP[0] = true; + for (int i = 1; i <= A.length; i++) { + for (int j = m; j >= 0; j--) { + if (j - A[i - 1] >= 0 && DP[j - A[i - 1]]) { + DP[j] = true; + } + } + } + + for (int j = m; j >= 0; j--) { + if (DP[j]) { + return j; + } + } + return 0; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Balanced Binary Tree.java b/Others/old records/LintCode-Backup/Balanced Binary Tree.java new file mode 100644 index 0000000..93b9c87 --- /dev/null +++ b/Others/old records/LintCode-Backup/Balanced Binary Tree.java @@ -0,0 +1,130 @@ +M + +1. DFS using depth marker: 每个depth都存一下。然后如果有不符合条件的,存为-1. + 一旦有-1, 就全部返回。 + 最后比较返回结果是不是-1. 是-1,那就false. + Traverse 整个tree, O(n) + +2. 从基本的题目理解考虑,想到leaf node的情况。如果判断了leaf node, 那其他node应该就是可以recursive。 + 直接在isBalanced上面recursive. + 关键return false的判断情况:如果有个node是null, 那么同一行相邻的那个,一旦有了children,那么就说明两个分支的depth已经是>=2了,那么就return false. + + 然后这个可能是个小小的优化,因为不需要计算所有的depth.一旦发现一个false,其他的就不需要计算,直接返回了。 + + +``` +/* +Given a binary tree, determine if it is height-balanced. + +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. + +Example +Given binary tree A={3,9,20,#,#,15,7}, B={3,#,20,15,7} + +A) 3 B) 3 + / \ \ + 9 20 20 + / \ / \ + 15 7 15 7 +The binary tree A is a height-balanced binary tree, but B is not. + +Tags Expand +Binary Search Divide and Conquer Recursion + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + +/* + 12.11.2015 + Recap: + The original way of marking depth and -1 is good. However, that has to traverse entire tree. + + Today, let's think about the leaf case, and see if we can directly recurse on isBalanced itself. + leaf case: + root == null, return true; + left = root.left; right = root.right; + left == null && right == null : true; + + left == null && right != null && (right.left != null || right.right != null) { + false; + } + + need to isBalance(left) && isBalance(right). +*/ + +public class Solution { + /** + * @param root: The root of binary tree. + * @return: True if this Binary tree is Balanced, or false. + */ + public boolean isBalanced(TreeNode root) { + if (root == null || (root.left == null && root.right == null)) { + return true; + } + + TreeNode left = root.left; + TreeNode right = root.right; + //One of left or right is null. + if (left == null && (right.left != null || right.right != null)) { + return false; + } + if (right == null && (left.left != null || left.right != null)) { + return false; + } + //none of left or right is null + return isBalanced(left) && isBalanced(right); + } +} + + +/* + +Thinking process: +making use depth first search. +same process as maxDepth() method. +after recursive call, check if Math.abs(left - right) > 1. If so, return -1. +If any case return -1, they all return -1. +at the top return, check if -1. + +*/ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: True if this Binary tree is Balanced, or false. + */ + public boolean isBalanced(TreeNode root) { + return maxDepth(root) != -1; + } + + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + int left = maxDepth(root.left); + int right = maxDepth(root.right); + + if (Math.abs(left - right) > 1 || left == -1 || right == -1) { + return -1; + } + + return Math.max(left, right) + 1; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock I.java b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock I.java new file mode 100644 index 0000000..f33f2dd --- /dev/null +++ b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock I.java @@ -0,0 +1,55 @@ +M + +理解意思是关键: + 每天都就交易价格,n天只让买卖一次,那就找个最低价买进,找个最高价卖出。 + 记录每天最小值Min是多少。O(n) + 每天都算和当下的Min买卖,profit最大多少。 + + +``` +/* +Say you have an array for which the ith element is the price of a given stock on day i. + +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. + +Have you met this question in a real interview? Yes +Example +Given an example [3,2,3,1,2], return 1 + +Tags Expand +Greedy Enumeration Array Facebook Uber + +*/ + +/* + +Thoughts +First to understand what this question is asking: +Each element is a price of the same stock on that specific day. Of course we want to buy in with min-price and sell out with max-price. +Find the min-price by looping through the array. +Find the max-profit: price[i] - min-price, which requires a loop through the loop again. +We put above 2 tasks into one-pass for loop + +*/ +public class Solution { + /** + * @param prices: Given an integer array + * @return: Maximum profit + */ + public int maxProfit(int[] prices) { + if (prices == null || prices.length == 0) { + return 0; + } + int min = Integer.MAX_VALUE; + int profit = 0; + for (int i = 0; i < prices.length; i++) { + min = Math.min(min, prices[i]); + profit = Math.max(profit, prices[i] - min); + } + return profit; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock II.java b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock II.java new file mode 100644 index 0000000..2ca5b6c --- /dev/null +++ b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock II.java @@ -0,0 +1,69 @@ +M + +和Stock I 的区别:可以买卖多次,求总和的最大盈利。 + +找涨幅最大的区间,买卖: +找到低谷,买进:peek = start + 1 时候,就是每次往前走一步;若没有上涨趋势,继续往低谷前进。 +涨到峰顶,卖出:一旦有上涨趋势,进一个while loop,涨到底, 再加个profit. + +中间的: + profit += prices[peek - 1] - prices[start]; 听特别的。 + 当没有上涨趋势时候,peek-1也就是start, 所以这里刚好profit += 0. + +O(n) + +``` +/* +Say you have an array for which the ith element is the price of a given stock on day i. + +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). + +Example +Given an example [2,1,2,0,1], return 2 + +Tags Expand +Greedy Enumeration Array +*/ + +/* +Thought: +In this case, since we know the entire stock price for all days in the array, we want to this: +Sell it at nearest peek price and buy it on the next dropped price, then sell again at next peek. +Two pointers, start and peek, to track the starting point and the peek. +Two while loop: +While loop on start, until start reaches the last 2nd index, we only have 1 option to sell. +Inner while loop that finds the peek from start. +Note: peek always has index >= start+1. +Sum up all profit and return it. +Tricky thing: we are looking for max profit, but does not require to sell the stock by end of array. +So if the price is dropping, we are not selling and we are not losing/winning anything. + +*/ +class Solution { + /** + * @param prices: Given an integer array + * @return: Maximum profit + */ + public int maxProfit(int[] prices) { + if (prices == null || prices.length == 0) { + return 0; + } + int profit = 0; + int start = 0; + int peek = 0; + while (start < prices.length - 1) { + peek = start + 1; + while (peek < prices.length && prices[peek - 1] <= prices[peek]) { + peek++; + } + profit += prices[peek - 1] - prices[start]; + start = peek; + } + return profit; + } +}; + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock III .java b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock III .java new file mode 100644 index 0000000..699e1d2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock III .java @@ -0,0 +1,73 @@ +M + +比stock II 多了一个限制:只有2次卖出机会。也就是:找峰头;然后往下再找一个峰头。 + +怎么样在才能Optimize两次巅峰呢? + +从两边同时开始找Max!(棒棒的想法) + + leftProfit是从左往右,每个i点上的最大Profit。 + rightProfit是从i点开始到结尾,每个点上的最大profit. + 那么在i点上,就是leftProfit,和右边rightProfit的分割点。在i点,leftProfit+rightProfit相加,找最大值。 + +三个O(n),还是O(n) + +``` +/* +Say you have an array for which the ith element is the price of a given stock on day i. + +Design an algorithm to find the maximum profit. You may complete at most two transactions. + +Example +Given an example [4,4,6,1,1,4,2,5], return 6. + +Note +You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). + +Tags Expand +Enumeration Forward-Backward Traversal Array + +*/ + +/* +Thoughts: +Idea from NineChapter: use two arrays to mark max values, however the max values are calculated from left/right sides. +Left[] marks max profit value in the range from a left-index to current index. Tracking left-min. +Right[] marks max profit value in the range from current index to a right-index. Tracking right-max. +If looking at right[i] and left[i] together at index i, they are always representing left-max-profit value and right-max-profit value. Add them together and get results. + +*/ +class Solution { + /** + * @param prices: Given an integer array + * @return: Maximum profit + */ + public int maxProfit(int[] prices) { + if (prices == null || prices.length == 0) { + return 0; + } + int[] leftProfit = new int[prices.length]; + int[] rightProfit = new int[prices.length]; + int min = prices[0]; //Default:leftProfit[0] = 0; + for (int i = 1; i < prices.length; i++) { + min = Math.min(min, prices[i]); + leftProfit[i] = Math.max(leftProfit[i - 1], prices[i] - min); + } + int max = prices[prices.length - 1]; //Default:rightProfit[prices.length - 1] = 0; + for (int i = prices.length - 2; i >= 0; i--) { + max = Math.max(max, prices[i]); + rightProfit[i] = Math.max(rightProfit[i + 1], max - prices[i]); + } + int profit = 0; + for (int i = 0; i < prices.length; i++) { + profit = Math.max(profit, leftProfit[i] + rightProfit[i]); + } + return profit; + } +}; + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock IV.java b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock IV.java new file mode 100644 index 0000000..4c79d7a --- /dev/null +++ b/Others/old records/LintCode-Backup/Best Time to Buy and Sell Stock IV.java @@ -0,0 +1,77 @@ +H + +记得要理解: 为什么 i-1天的卖了又买,可以和第 i 天的卖合成一次交易? + 因为每天交易的price是定的。所以卖了又买,等于没卖!这就是可以合并的原因。要对价格敏感啊少年。 + +Inspired from here: +http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html + +局部最优解 vs. 全局最优解: + local[i][j] = max(global[i – 1][j – 1] + diff, local[i – 1][j] + diff) + global[i][j] = max(global[i – 1][j], local[i][j]) + +local[i][j]和global[i][j]的区别是:local[i][j]意味着在第i天一定有交易(卖出)发生。 + 当第i天的价格高于第i-1天(即diff > 0)时,那么可以把这次交易(第i-1天买入第i天卖出)跟第i-1天的交易(卖出)合并为一次交易,即local[i][j]=local[i-1][j]+diff; + 当第i天的价格不高于第i-1天(即diff<=0)时,那么local[i][j]=global[i-1][j-1]+diff,而由于diff<=0,所以可写成local[i][j]=global[i-1][j-1]。 + (Note:在我下面这个solution里面没有省去 +diff) + +global[i][j]就是我们所求的前i天最多进行k次交易的最大收益,可分为两种情况: + 如果第i天没有交易(卖出),那么global[i][j]=global[i-1][j]; + 如果第i天有交易(卖出),那么global[i][j]=local[i][j]。 + + + +``` +/* +Say you have an array for which the ith element is the price of a given stock on day i. + +Design an algorithm to find the maximum profit. You may complete at most k transactions. + +Example +Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6. + +Note +You may not engage in multiple transactions at the same time +(i.e., you must sell the stock before you buy again). + +Challenge +O(nk) time. + +Tags Expand +Dynamic Programming +*/ + +/* + Thoughts: http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html + local[i][j] = max(global[i – 1][j – 1] , local[i – 1][j] + diff). WHY???? + global[i][j] = max(global[i – 1][j], local[i][j]) + +*/ +class Solution { + public int maxProfit(int k, int[] prices) { + if (prices == null || prices.length < 2 || k <= 0) { + return 0; + } + if (k >= prices.length) { + int profit = 0; + for (int i = 1; i < prices.length; i++) { + if (prices[i] > prices[i - 1]) { + profit += prices[i] - prices[i - 1]; + } + } + return profit; + } + int[][] local = new int[prices.length][k + 1]; + int[][] global = new int[prices.length][k + 1]; + for (int i = 1; i < prices.length; i++) { + int diff = prices[i] - prices[i - 1]; + for (int j = 1; j <= k; j++) { + local[i][j] = Math.max(global[i-1][j-1] + diff, local[i - 1][j] + diff); + global[i][j] = Math.max(global[i-1][j], local[i][j]); + } + } + return global[prices.length - 1][k]; + } +}; + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Representation.java b/Others/old records/LintCode-Backup/Binary Representation.java new file mode 100644 index 0000000..188d5e6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Representation.java @@ -0,0 +1,114 @@ +H + +首先要分两半解决,断点是'.': str.split("\\."); + +Integer那一半好弄,whie loop里: num%2, num/2。 + +Decimal那边复杂点. + bit == 1的数学条件:当下num * 2 >= 1。 更新: num = num * 2 - 1; + bit == 0的数学条件: num * 2 < 1. 更新: num = num * 2 + +注意:num是 double, 小数在 (num = num * 2 -1)的公式下可能无限循环. 因此check: num重复性,以及binary code < 32 bit. + +(所以题目也才有了32BIT的要求!) + +``` +/* +Given a (decimal - e.g. 3.72) number that is passed in as a string, +return the binary representation that is passed in as a string. +If the fractional part of the number can not be represented accurately in binary with at most 32 characters, return ERROR. + +Example +For n = "3.72", return "ERROR". + +For n = "3.5", return "11.1". + +Tags Expand +String Cracking The Coding Interview Bit Manipulation + +*/ + +/* + +Thoughts: +Expan the value for binary representation: +8, 4, 2, 1, 0.5, 0.25 ... etc +3, 2, 1, 0, -1, -2, ... etc + +1. Think of a good method to split the number into front . end part. +2. Deal with integer transforming into binary: integer divided by 2 see if != 0 +3. Deal with double transforming into binary: times 2 see if >= 1 + +Split: split string by '.'. +Checkfloat first: if float part is '0' or "", can just move on the integer part. + +Note: str.split("\\.") +Note2: use a set to prevent infinite loop on float: +for example: 2x - 1 = x -> x = 1. that will cause infinite loop. + +*/ +public class Solution { + public String binaryRepresentation(String n) { + if (n.length() == 0 || n.equals("0")) { + return "0"; + } + //If no '.', no decimal, just parseInteger + if (n.indexOf(".") == -1) { + return parseInteger(n); + } + //Split the string by '.' + String[] strs = n.split("\\."); + //Deal with decimal first. + String decimal = parseDecimal(strs[1]); + //If not applicable, it won't work, don't need to calculate integer part. Just return ERROR. + if (decimal.equals("ERROR")) { + return decimal; + } + //Deal with integer part + if (decimal.length() == 0 || decimal.equals("0")) { + return parseInteger(strs[0]); + } else { + return parseInteger(strs[0]) + "." + decimal; + } + } + + public String parseInteger(String n) { + if (n.length() == 0 || n.equals("0")) { + return n; + } + int num = Integer.parseInt(n); + String rst = ""; + while (num != 0) { + rst = num % 2 + rst;//mod(2) -> binary representation + num = num / 2;//小时候转换二进制也是这样。 + } + return rst; + } + // A little bit math, but implemtable. + public String parseDecimal(String n) { + if (n.length() == 0 || n.equals("0")) { + return ""; + } + //A doublem must be able to catch it. If not, that is way bigger than 32 bit. + double num = Double.parseDouble("0." + n); + //Check existance + HashSet set = new HashSet(); + String rst = ""; + while (num > 0) { + if (rst.length() > 32 || set.contains(num)) { + return "ERROR"; + } + set.add(num); + //For decimal: binary code on one spot == 1, means: num * 2 - 1 > 0 + if (num * 2 >= 1) { + rst = rst + "1"; + num = num * 2 - 1; + } else { + rst = rst + "0"; + num = num * 2; + } + } + return rst; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Search Tree Iterator.java b/Others/old records/LintCode-Backup/Binary Search Tree Iterator.java new file mode 100644 index 0000000..7ab684a --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Search Tree Iterator.java @@ -0,0 +1,199 @@ +M + +用O(h)空间的做法: + +理解binary search tree inorder traversal的规律: + 先找left.left.left ....left 到底,这里是加进stack. + 然后考虑parent,然后再right. + +例如这题: + stack里面top,也就是tree最左下角的node先考虑,取名rst. + 其实这个rst拿出来以后, 它也同时是最底层left null的parent,算考虑过了最底层的parent。 + 最后就考虑最底层的parent.right, 也就是rst.right. + +注意: + next()其实有个while loop, 很可能是O(h).题目要求average O(1),所以也是okay的. + + +用O(1)空间的做法:不存stack, 时刻update current为最小值。 + +找下一个最小值: + 如果current有right child,那么再找一遍current.right的left-most child,就是最小值了。 + 如果current没有right child,那么就要找current node的右上parent. + +注意: + 一定要确保找到的parent满足parent.left == current. + 反而言之,如果current是parent的 right child, 那么下一轮就会重新process parent。 + 但是有错:binary search tree里面parent是小于right child的,也就是在之前一步肯定visit过,如此便会死循环。 + + +``` +/* +Design an iterator over a binary search tree with the following rules: + +Elements are visited in ascending order (i.e. an in-order traversal) +next() and hasNext() queries run in O(1) time in average. + +Example +For the following binary search tree, in-order traversal by using iterator is [1, 6, 10, 11, 12] + + 10 + / \ +1 11 + \ \ + 6 12 +Challenge +Extra memory usage O(h), h is the height of the tree. + +Super Star: Extra memory usage O(1) + +Tags Expand +Binary Tree LintCode Copyright Non Recursion Binary Search Tree Google LinkedIn Facebook +*/ + + + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + * Example of iterate a tree: + * BSTIterator iterator = new BSTIterator(root); + * while (iterator.hasNext()) { + * TreeNode node = iterator.next(); + * do something for node + * } + */ +/* + Thoughts:http://blog.csdn.net/u014748614/article/details/46800891 + Put all left nodes into stack. Then top of stack must be the first element in in-order-traversal. + We never add right node into stack directly, but ever time before returnning the rst node, we take care of rst.right right away. + That is, find next() when rst.right as root. + very smart use of a 'currnt' node. + It's like a pointer on the tree, but only operates when that current node is not null, and under condition of having left child. + +*/ + +public class BSTIterator { + public Stack stack = new Stack(); + public TreeNode current; + //@param root: The root of binary tree. + public BSTIterator(TreeNode root) { + current = root; + } + + //@return: True if there has next node, or false + public boolean hasNext() { + return current != null || !stack.isEmpty(); + } + + //@return: return next node + public TreeNode next() { + while (current != null) { + stack.push(current); + current = current.left; + } + TreeNode rst = stack.pop(); + current = rst.right; + return rst; + } +} + +/* + Use O(1) space, which means we will not use O(h) stack. + + To begin: + 1. hasNext()? current.val <= endNode.val to check if the tree is fully traversed. + + 2. Find min via left-most: We can alwasy look for left-most to find next minimum value. + + 3. Once left-most min is checked (name it `current`). Next min will be 2 cases: + If current.right != null, we can keep looking for current.right's left-most child, as next min. + Or, we need to look backwards for parent. Use binary search tree to find current's parent node. + + Note: when doing binary search for parent, make sure it satisfies parent.left = current. + + Because:If parent.right == current, that parent must has been visited before. In binary search tree, + we know that parent.val < parent.right.val. We need to skip this special case, since it leads + to ifinite loop. + +*/ + + +public class BSTIterator { + public TreeNode root; + public TreeNode current; + public TreeNode endNode; + //@param root: The root of binary tree. + public BSTIterator(TreeNode root) { + if (root == null) { + return; + } + this.root = root; + this.current = root; + this.endNode = root; + + while (endNode != null && endNode.right != null) { + endNode = endNode.right; + } + while (current != null && current.left != null) { + current = current.left; + } + } + + //@return: True if there has next node, or false + public boolean hasNext() { + return current != null && current.val <= endNode.val; + } + + //@return: return next node + public TreeNode next() { + TreeNode rst = current; + //current node has right child + if (current.right != null) { + current = current.right; + while (current.left != null) { + current = current.left; + } + } else {//Current node does not have right child. + current = findParent(); + } + return rst; + } + + //Find current's parent, where parent.left == current. + public TreeNode findParent(){ + TreeNode node = root; + TreeNode parent = null; + int val = current.val; + if (val == endNode.val) { + return null; + } + while (node != null) { + if (val < node.val) { + parent = node; + node = node.left; + } else if (val > node.val) { + node = node.right; + } else {//node.val == current.val + break; + } + } + return parent; + } +} + + +``` + + + + + + diff --git a/Others/old records/LintCode-Backup/Binary Tree Inorder Traversal.java b/Others/old records/LintCode-Backup/Binary Tree Inorder Traversal.java new file mode 100644 index 0000000..1b98ec6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Inorder Traversal.java @@ -0,0 +1,117 @@ +E + +法一: +Recursive: Divide and Conquer, with helper method + +法二: +Stack: +Add left nodes all the way +Print curr +Move to right, add right if possible. + +注意stack.pop()在加完left-most child 的后,一定要curr = curr.right. + +若不右移,很可能发生窘境: +curr下一轮还是去找自己的left-most child,不断重复curr and curr.left, 会infinite loop, 永远在左边上下上下。 + + +``` +/* +Given a binary tree, return the inorder traversal of its nodes' values. + +Example +Given binary tree {1,#,2,3}, + + 1 + \ + 2 + / + 3 + + +return [1,3,2]. + +Challenge +Can you do it without recursion? + +Tags Expand +Recursion Binary Tree Binary Tree Traversal + +*/ + +/* + 1. Use a helper method, recursively add to rst +*/ + +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Inorder in ArrayList which contains node values. + */ + public ArrayList inorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + helper(rst, root); + + return rst; + } + + public void helper(ArrayList rst, TreeNode node) { + if (node == null) { + return; + } + helper(rst, node.left); + rst.add(node.val); + helper(rst, node.right); + } +} + +/* + 2. Non-recursive + Inorder traversal: use 1 stack, push left till end; pirnt/store curr; push right to stack + 'Curr' is always moving along with the curret position, representing the current node. + + Note: after curr = curr.right, curr could be null; this will skip the while loop, and move on to next element. + + Trick: in Inorder, we care the right node least. So we keep going with left and curr; + only when there is a right node, we add it; + even after this, we go deep into that right node's left children all the way down. +*/ + +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Inorder in ArrayList which contains node values. + */ + public ArrayList inorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + + Stack stack = new Stack(); + TreeNode curr = root; + stack.add(curr); + while (!stack.isEmpty()) { + while (curr != null && curr.left != null) { + stack.push(curr.left); + curr = curr.left; + } + //Pop the top node: the curr node + curr = stack.pop(); + rst.add(curr.val); + //Move to right node, and push to stack if needed + curr = curr.right; + if (curr!= null) { + stack.push(curr); + } + } + return rst; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal II.java b/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal II.java new file mode 100644 index 0000000..a8dedfd --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal II.java @@ -0,0 +1,104 @@ +M + +普通BFS,用一个queue,加上一个queue.size()来交替换行. + + +``` + +/* +Given a binary tree, return the bottom-up level order traversal of its nodes' values. +(ie, from left to right, level by level from leaf to root). + +Example +Given binary tree {3,9,20,#,#,15,7}, + + 3 + / \ + 9 20 + / \ + 15 7 + + +return its bottom-up level order traversal as: + +[ + [15,7], + [9,20], + [3] +] +Tags Expand +Queue Binary Tree Binary Tree Traversal Breadth First Search +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + + /* + +Thoughts: +1. Non-recursive +similar to Binary Tree Level Order Traversal I, just when adding into the final result, +add to the top all the time. Then the first added will be at the bottom: result.add(0, list) +2. Recursive: + Similar to Level Traversal I, do a dfs. The difference is: everytime, we use ArrayList> like a stack by doing add(0, newList); + when populating the levelArrayList, make sure to address the correct corresponding level. + + */ + +public class Solution { + /** + * @param root: The root of binary tree. + * @return: buttom-up level order a list of lists of integer + */ + public ArrayList> levelOrderButtom(TreeNode root) { + ArrayList> result = new ArrayList>(); + if (root == null) { + return result; + } + /* + Queue queue = new LinkedList(); + queue.offer(root); + + while (!queue.isEmpty()) { + ArrayList list = new ArrayList(); + int size = queue.size(); + for (int i = 0; i < size; i++) { + TreeNode temp = queue.poll(); + list.add(temp.val); + if (temp.left != null) { + queue.offer(temp.left); + } + if (temp.right != null) { + queue.offer(temp.right); + } + } + result.add(0, list); + }*/ + + dfs(root, 0, result); + return result; + } + public void dfs(TreeNode root, int level, ArrayList> rst) { + if (root == null) { + return; + } + if (level >= rst.size()) { + rst.add(0, new ArrayList()); + } + dfs(root.left, level + 1, rst); + dfs(root.right, level + 1, rst); + rst.get(rst.size() - level - 1).add(root.val); + } +} + +``` diff --git a/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal.java b/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal.java new file mode 100644 index 0000000..aa2d884 --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Level Order Traversal.java @@ -0,0 +1,170 @@ +M + +方法1. 最普通,Non-recursive: BFS, queue, 用个queue.size()来end for loop:换行。 + 或者用两个queue. 当常规queue empty,把backup queue贴上去。 + +方法2. Recursive with dfs: + 每个level都应该有个ArrayList. 那么用一个int level来查看:是否每一层都有了相应的ArrayList。 + 如果没有,就加上一层。 + 之后每次都通过DFS在相应的level上面加数字。 + + +``` +/* +Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). + +Example +Given binary tree {3,9,20,#,#,15,7}, + + 3 + / \ + 9 20 + / \ + 15 7 + + +return its level order traversal as: + +[ + [3], + [9,20], + [15,7] +] +Challenge +Challenge 1: Using only 1 queue to implement it. + +Challenge 2: Use DFS algorithm to do it. + +Tags Expand +Queue Binary Tree Breadth First Search Binary Tree Traversal Uber LinkedIn Facebook + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + +/* +Thoughts: +1. Non-recursive +Use queue to withhold the parent. +Poll one parent, add this parent’s value to arrayList +Add the children into Arraylist +jump to next level +2. Recursive +use a integer to track levels. +If at a new level, then create a new ArrayList. +At each node, add the node to corresponding level-ArrayList +*/ + +//Non-recurive Iterative way: +//Even with while + for nested loop, it's just O(n) +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Level order a list of lists of integer + */ + public ArrayList> levelOrder(TreeNode root) { + ArrayList> result = new ArrayList>(); + if (root == null) { + return result; + } + + //Use a queue to list elements: each row + Queue queue = new LinkedList(); + queue.offer(root); + + while (!queue.isEmpty()) { + ArrayList list = new ArrayList(); + int size = queue.size();//Limit the size, since the queue is increasing + for (int i = 0; i < size; i++) { + TreeNode levelNode = queue.poll(); + list.add(levelNode.val);//Add all the values from this current level + if (levelNode.left != null) { + queue.offer(levelNode.left); + } + if (levelNode.right != null) { + queue.offer(levelNode.right); + } + } + result.add(list); + }//while + + return result; + } +} + +//Another Iterative way: using 2 Queues +public class Solution { + public List> levelOrder(TreeNode root) { + List> rst = new ArrayList>(); + if (root == null) { + return rst; + } + Queue queue = new LinkedList(); + Queue backQueue = new LinkedList(); + queue.offer(root); + ArrayList list = new ArrayList(); + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (node.left != null) { + backQueue.offer(node.left); + } + if (node.right != null) { + backQueue.offer(node.right); + } + list.add(node.val); + + if (queue.isEmpty()) { + rst.add(new ArrayList(list)); + list = new ArrayList(); + queue = backQueue; + backQueue = new LinkedList(); + } + + } + return rst; + } +} + + + +//Recursive: +//Recursive with dfs: use a level to track. Add curr into corresponding level; each level > rst.size(), add a new []. +//Note: rst is a ArrayList>, where each level is a arraylist; that is why we can add [] into rst to represent a level. + +public class Solution { + public ArrayList> levelOrder(TreeNode root) { + ArrayList> result = new ArrayList>(); + if (root == null) { + return result; + } + + dfs(root, 0, result); + return result; + } + + public void dfs(TreeNode root, int level, ArrayList> rst) { + if (root == null) { + return; + } + if (level >= rst.size()) { + rst.add(new ArrayList()); + } + rst.get(level).add(root.val); + dfs(root.left, level + 1, rst); + dfs(root.right, level + 1, rst); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum II.java b/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum II.java new file mode 100644 index 0000000..16dbcff --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum II.java @@ -0,0 +1,71 @@ +M + +比Binary Tree Maximum Path Sum I 简单许多. + +因为条件给的更多:at least 1 node + have to start from root => have to have root. + +Single path: either left or right. +If the path sum < 0, just skip it. + +``` +/* +Binary Tree Maximum Path Sum II + +Given a binary tree, find the maximum path sum from root. + +The path may end at any node in the tree and contain at least one node in it. + +Example +Given the below binary tree: + + 1 + / \ +2 3 +return 4. (1->3) + +Tags Expand +Binary Tree +*/ + +/* + Thoughts: maximum path sum from root, so it must include root, and it will be a single path + from root to some point in the tree. + (seems easier than Binary Tree Maximum path Sum I) + 'contains at least 1 node' -> at least have root. + However, depending on child is positive or negative, we choose add or no add child +*/ +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root the root of binary tree. + * @return an integer + */ + public int maxPathSum2(TreeNode root) { + if (root == null) { + return 0; + } + return Math.max(helper(root.left),helper(root.right)) + root.val; + } + + public int helper(TreeNode node) { + if (node == null) { + return 0; + } else if (node.left == null && node.right == null) { + return node.val > 0 ? node.val : 0; + } + int sum = Math.max(helper(node.left), helper(node.right)) + node.val; + return sum > 0 ? sum : 0; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum.java b/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum.java new file mode 100644 index 0000000..1d2ad38 --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Maximum Path Sum.java @@ -0,0 +1,116 @@ +M + +第一次做有点难理解,复杂原因是:因为可能有负值啊。不能乱assume正数。 + single path max 的计算是为了给后面的comboMax用的。 + 如果single path max小于0,那没有什么加到parent上面的意义,所以就被再次刷为0. + +combo的三种情况:(root可能小于0) + 1. 只有left + 2。 只有右边 + 3. root大于0,那么就left,right,curr全部加起来。 + +情况1和情况2去一个最大值,然后和情况三比较。做了两个Math.max(). 然后就有了这一层的comboMax + + +12.11.2015 recap: + So totally, 5 conditions: + (save in single) + left + curr.val OR right + curr.val + (save in combo:) + left, right, OR left + curr.val + right + + + +``` +/* +Given a binary tree, find the maximum path sum. + +The path may start and end at any node in the tree. + + +Example +Given the below binary tree: + + 1 + / \ +2 3 +return 6. + +Tags Expand +Divide and Conquer Dynamic Programming Recursion + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + + +/* +Thoughts: +Don't assume positive integers . + +Two ways of picking nodes: 1. Single Path (left or right)has a maximum. 2. Combine them into a final result: combinedPathMax + +1. singlePathMax, two results: either pick left+root or right+root. +2. combinedPathMax: take left-max as a whole, take right-max as a whole. + 3 possible results: left-max without parent(like...when parent<0), right-max without parent(like...when parent<0), left-max + right-max + parent. +3. Use a special container to store current node's singlePathMax and combinedPathMax. + +Note:12.03.2015 +It's complex, because we could have nagative number. + +Combo is compared through: just left, just right, or combo of all. +*/ +public class Solution { + private class PathSumType { + int singlePathMax; + int combinedPathMax; + PathSumType(int singlePathMax, int combinedPathMax) { + this.singlePathMax = singlePathMax; + this.combinedPathMax = combinedPathMax; + } + } + /** + * @param root: The root of binary tree. + * @return: An integer. + */ + public int maxPathSum(TreeNode root) { + PathSumType result = helper(root); + return result.combinedPathMax; + } + + public PathSumType helper(TreeNode root) { + if (root == null) { + return new PathSumType(0, Integer.MIN_VALUE); + } + //Divide + PathSumType left = helper(root.left); + PathSumType right = helper(root.right); + //Conquer + //Step 1: prepare single path max for parent-level comparison. + int singlePathMax = Math.max(left.singlePathMax, right.singlePathMax) + root.val; + singlePathMax = Math.max(singlePathMax, 0);//If less than 0, no need to keep, because it only decrease parent-level max. + + //first comparison: does not include root node at all(this would be applicable when curr.val < 0, so we take this condition into account) + int combinedPathMax = Math.max(left.combinedPathMax, right.combinedPathMax); + //second comparison: + combinedPathMax = Math.max(combinedPathMax, left.singlePathMax + right.singlePathMax + root.val); + + return new PathSumType(singlePathMax, combinedPathMax); + } + +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Path Sum.java b/Others/old records/LintCode-Backup/Binary Tree Path Sum.java new file mode 100644 index 0000000..95ab61e --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Path Sum.java @@ -0,0 +1,87 @@ +E + +Binary Tree的一个基本题。 +遍历到底,比较sum vs. target。 +注意divde的情况。要把遍历的例子写写。 + +``` +/* +Given a binary tree, find all paths that sum of the nodes in the path equals to a given number target. + +A valid path is from root node to any of the leaf nodes. + +Example +Given a binary tree, and target = 5: + + 1 + / \ + 2 4 + / \ + 2 3 +return + +[ + [1, 2, 2], + [1, 4] +] +Tags Expand +Binary Tree Binary Tree Traversal +*/ + +/* + Thoughts: + path: has to be from root to leaf. + binary tree: no order logic in the tree. + DPS on all nodes. If final sum == target, add list of nodes into rst +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + +public class Solution { + public List> binaryTreePathSum(TreeNode root, int target) { + List> rst = new ArrayList>(); + if (root == null) { + return rst; + } + ArrayList list = new ArrayList(); + list.add(root.val); + traversal(rst, list, root, root.val, target); + return rst; + } + + + public void traversal(List> rst, ArrayList list, TreeNode node, int sum, int target) { + if (node.left == null && node.right == null) { + if (sum == target) { + rst.add(new ArrayList(list)); + } + return; + } + if (node.left != null) { + list.add(node.left.val); + traversal(rst, list, node.left, sum + node.left.val, target); + list.remove(list.size() - 1); + } + if (node.right != null) { + list.add(node.right.val); + traversal(rst, list, node.right, sum + node.right.val, target); + list.remove(list.size() - 1); + } + } +} + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Paths.java b/Others/old records/LintCode-Backup/Binary Tree Paths.java new file mode 100644 index 0000000..f15a24c --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Paths.java @@ -0,0 +1,157 @@ +E + +方法1: +Recursive:分叉。Helper。 + +方法2,Iterative: + 非递归练习了一下 + 因为要每次切短list, 所以再加了一个Stack 来存level + + +``` +/* +Binary Tree Paths + +Given a binary tree, return all root-to-leaf paths. + +Example +Given the following binary tree: + + 1 + / \ +2 3 + \ + 5 +All root-to-leaf paths are: + +[ + "1->2->5", + "1->3" +] +Tags Expand +Binary Tree Binary Tree Traversal Facebook Google +*/ + +/* + Thoughts: + Recursive, need a helper (root, arraylist list, List) + Add curr. + if(root.left == null && root.right == null) { + convert to String, add to list. + } + Go left. remove last node. + Go right, remove last node. + + time: 2715m +*/ + +public class Solution { + /** + * @param root the root of the binary tree + * @return all root-to-leaf paths + */ + public List binaryTreePaths(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + helper(root, rst, new ArrayList()); + return rst; + } + + public void helper(TreeNode root, List rst, ArrayList list){ + list.add(root.val); + if (root.left == null && root.right == null) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size() - 1; i++) { + sb.append(list.get(i) + "->"); + } + sb.append(list.get(list.size() - 1)); + rst.add(sb.toString()); + } + if (root.left != null) { + helper(root.left, rst, list); + list.remove(list.size() - 1); + } + if (root.right != null) { + helper(root.right, rst, list); + list.remove(list.size() - 1); + } + } +} + + +/* + Iterative: + Use a stack. Note. Process push curr, right, left + Special: use a levels stack, to track level. Because we are not backtracking in interative mode, + so we need manually adjust list's length back to be same level as next item in stack. + time: 2715m +*/ + +public class Solution { + public List binaryTreePaths(TreeNode root) { + List rst = new ArrayList(); + if (root == null) { + return rst; + } + Stack stack = new Stack(); + ArrayList list = new ArrayList(); + stack.push(root); + + Stack levels = new Stack(); + levels.push(0); + + while (!stack.isEmpty()) { + int lv = levels.pop(); + TreeNode node = stack.pop(); + list.add(node.val); + + if (node.left == null && node.right == null) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size() - 1; i++) { + sb.append(list.get(i) + "->"); + } + sb.append(list.get(list.size() - 1)); + rst.add(sb.toString()); + while (!levels.isEmpty() && list.size() > levels.peek()) { + list.remove(list.size() - 1); + } + } + + if (node.right != null) { + stack.push(node.right); + levels.push(lv + 1); + } + if (node.left != null) { + stack.push(node.left); + levels.push(lv + 1); + } + + }//end while + + return rst; + } +} +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Postorder Traversal.java b/Others/old records/LintCode-Backup/Binary Tree Postorder Traversal.java new file mode 100644 index 0000000..68ed22d --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Postorder Traversal.java @@ -0,0 +1,137 @@ +E + +最prefer 2 stack的做法: + stack1和stack2合作。倒水。记这个做法。。。挺神奇的。 + +Divide and Conquer 的recursive方法也非常明了! + +注意,这些binary tree traversal的题目,常常有多个做法:recursive or iterative + +``` +/* +Binary Tree Postorder Traversal +Given a binary tree, return the postorder traversal of its nodes' values. + +Example +Given binary tree {1,#,2,3}, + + 1 + \ + 2 + / + 3 + + +return [3,2,1]. + +Challenge +Can you do it without recursion? + +Tags Expand +Binary Tree + +*/ + +/* + +Thinking process: +1. Resursive: (divide and conquer) + rec on left node + rec on right node + rst.addAll(left) + rst.addAll(right) + rst.add(curr) + +*/ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Postorder in ArrayList which contains node values. + */ + public ArrayList postorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + //Recursive: + ArrayList right = postorderTraversal(root.right); + ArrayList left = postorderTraversal(root.left); + rst.addAll(left); + rst.addAll(right); + rst.add(root.val); + return rst; + } +} + + +/* + 2. Non-recursive, iterative + use 2 stacks: pull water from s1 into s2 + in s2, we want: at each level, parentNode at bottom, then rightNode, then leftNode + loop through s2, then we print out leftNode, rightNode, parentNode ... in postOrder. +*/ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Postorder in ArrayList which contains node values. + */ + public ArrayList postorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + //Non-recursive: + Stack s1 = new Stack(); + Stack s2 = new Stack(); + s1.push(root); + while (!s1.empty()) { + TreeNode curr = s1.pop(); + s2.push(curr); + if (curr.left != null) { + s1.push(curr.left); + } + if (curr.right != null) { + s1.push(curr.right); + } + } + while (!s2.empty()) { + rst.add(s2.pop().val); + } + return rst; + } +} + + +/* + Recap 12.08.2015 + Besides the 2 old ways of doing it, we can: + 3. Recursive with helper method. + +*/ +//Recursive with helper +public class Solution { + public ArrayList postorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + helper(rst, root); + return rst; + } + + public void helper(ArrayListrst, TreeNode node) { + if (node == null) { + return; + } + if (node.left == null && node.right == null) { + rst.add(node.val); + return; + } + helper(node.left); + helper(node.right); + rst.add(node.val); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Preorder Traversal.java b/Others/old records/LintCode-Backup/Binary Tree Preorder Traversal.java new file mode 100644 index 0000000..1fb121f --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Preorder Traversal.java @@ -0,0 +1,172 @@ +E + +Preorder 写写, stack +1. Divide and conquer +2. Stack(NON-recursive) push curr, push right, push left. +3. recursive with helper method + +``` +/* +Given a binary tree, return the preorder traversal of its nodes' values. + +Note +Given binary tree {1,#,2,3}, + + 1 + \ + 2 + / + 3 + + +return [1,2,3]. + +Example +Challenge +Can you do it without recursion? + +Tags Expand +Tree Binary Tree +//Recommend way: using a stack +//Recursive way can be seen here: http://www.ninechapter.com/solutions/binary-tree-preorder-traversal/ + +*/ + +/* + + Recap: 12.08.2015 + Draw a few nodes and will realize to use stack + Cannot use queue, because whatever added on it first, will first process. + That means if we add curr,left,right; they will be processed first... but we want to traverse all left nodes first. + IN FACT: binary tree traversal are all using stack... +*/ + +//Itereative +public class Solution { + + public ArrayList preorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + Stack stack = new Stack(); + stack.push(root); + while (!stack.isEmpty()) { + TreeNode node = stack.pop(); + if (node != null) { + rst.add(node.val); + stack.push(node.right); + stack.push(node.left); + } + } + return rst; + } +} + +//recursive +public class Solution { + public ArrayList preorderTraversal(TreeNode root) { + ArrayList rst = new ArrayList(); + if (root == null) { + return rst; + } + helper(rst, root); + return rst; + } + + public void helper(ArrayListrst, TreeNode node){ + if (node != null) { + rst.add(node.val); + helper(rst, node.left); + helper(rst, node.right); + } + } +} + + + + +/* +Thinking process: +Check if root is null +use a container to save results + +use current node +put right on stack +put left on stack +4. In next run, the ‘left’ will be on top of stack, and will be taken first. So the order becomes: parent -> left -> right + +*/ +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: Preorder in ArrayList which contains node values. + */ + public ArrayList preorderTraversal(TreeNode root) { + Stack stack = new Stack(); + ArrayList result = new ArrayList(); + //Check top + if (root == null) { + return result; + } + //save root + stack.push(root); + //add to result, and load on stack. Right-side at the bottom + while (!stack.empty()) { + TreeNode node = stack.pop(); + result.add(node.val); + if (node.right != null) { + stack.push(node.right); + } + if (node.left != null) { + stack.push(node.left); + } + }//while + + return result; + } +} + + + +//Divide and Conquer - recursive +/* +Check root == null? +Dive them into 2 recursive calls: get result from left, get result from right +Conquer - add all of the results together and return. As the pre-order defines: +add current parent +add left nodes +add right nodes. +*/ + + //Divide and conquer + public ArrayList preorderTraversal(TreeNode root) { + // write your code here + ArrayList result = new ArrayList(); + + if (root == null) { + return result; + } + ArrayList left = preorderTraversal(root.left); + ArrayList right = preorderTraversal(root.right); + + result.add(root.val); + result.addAll(left); + result.addAll(right); + + return result; + } + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Binary Tree Zigzag Level Order Traversal.java b/Others/old records/LintCode-Backup/Binary Tree Zigzag Level Order Traversal.java new file mode 100644 index 0000000..fda05d8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Binary Tree Zigzag Level Order Traversal.java @@ -0,0 +1,91 @@ +/* 24% Accepted +Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). + +Example +Given binary tree {3,9,20,#,#,15,7}, + + 3 + / \ + 9 20 + / \ + 15 7 + + +return its zigzag level order traversal as: + +[ + [3], + [20,9], + [15,7] +] +Tags Expand +Tree Search Breadth First Search Queue Binary Tree + +Thinking Process: +1. realize: queue is no longer can be used. draw a example map to see why. +Instead, use 2 stacks. +Because we can only take the top of stack, and we are constantly adding to the top of the stac, so we need 2 stacks. One is the current one, will be empty every time when we finish the level. The other one is nextLevel, which holds next level’s nodes temporarily. +2. Use a boolean to track if which level it’s running at. +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + +public class Solution { + /** + * @param root: The root of binary tree. + * @return: A list of lists of integer include + * the zigzag level order traversal of its nodes' values + */ + public ArrayList> zigzagLevelOrder(TreeNode root) { + ArrayList> result = new ArrayList>(); + if (root == null) { + return result; + } + + Stack currentLevel = new Stack(); + Stack nextLevel = new Stack(); + + currentLevel.push(root); + boolean regularOrder = false; + + while (!currentLevel.empty()) { + ArrayList list = new ArrayList(); + + while (!currentLevel.empty()) { + TreeNode temp = currentLevel.pop(); + list.add(temp.val); + if (regularOrder) { + addLevel(nextLevel, temp.right); + addLevel(nextLevel, temp.left); + } else { + addLevel(nextLevel, temp.left); + addLevel(nextLevel, temp.right); + } + } + result.add(list); + regularOrder = !regularOrder; + Stack tmp = currentLevel; + currentLevel = nextLevel; + nextLevel = tmp; + } + return result; + } + + public void addLevel(Stack level, TreeNode node) { + if (node != null) { + level.push(node); + } + } +} + diff --git a/Others/old records/LintCode-Backup/Building Outline.java b/Others/old records/LintCode-Backup/Building Outline.java new file mode 100644 index 0000000..994b2b6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Building Outline.java @@ -0,0 +1,229 @@ +/* +Given N buildings in a x-axis,each building is a rectangle and can be represented by a triple (start, end, height),where start is the start position on x-axis, end is the end position on x-axis and height is the height of the building. Buildings may overlap if you see them from far away,find the outline of them。 +An outline can be represented by a triple, (start, end, height), where start is the start position on x-axis of the outline, end is the end position on x-axis and height is the height of the outline. +Example +Given 3 buildings: +[ + [1, 3, 3], + [2, 4, 4], + [5, 6, 1] +] +The outlines are: +[ + [1, 2, 3], + [2, 4, 4], + [5, 6, 1] +] +Note +Please merge the adjacent outlines if they have the same height and make sure different outlines cant overlap on x-axis. +Tags Expand +LintCode Copyright Heap +*/ +/* +Thoughts: +Well, based on JiuZhang, http://www.jiuzhang.com/solutions/building-outline/, implement a HashHeap. +**HashHeap. Super long implementation: http://www.jiuzhang.com/solutions/hash-heap/ +*/ + + + + + +/**** + Attempt1, may not be correct. + Thoughts: + PriorityQueue, sort by start. + 1. Keep track of max height. + 2. Find max height. + 3. Poll() queue. Whenever there is a jump(up or down) at current node, close a interval. + 4. When closing interval, set prev = new node.h +****/ + + +/** + +What is HashHeap Exactly? Document below: + +**/ +class HashHeap { + //Heap is a arraylist, which stores the actaul Integer values. It stores the real data + ArrayList heap; + //HashMap stores the actual value, and the corresponding node. + HashMap hash; + String mode; + int size_t; + + /* + Used in HashMap, + id: id in the Heap tree + num: The frequency of the appearance of this id. + */ + class Node { + public Integer id; + public Integer num; + + Node(Node now) { + id = now.id; + num = now.num; + } + + Node(Integer first, Integer second) { + + this.id = first; + this.num = second; + } + } + + public HashHeap(String mod) { // 传入min 表示最小堆,max 表示最大堆 + // TODO Auto-generated constructor stub + heap = new ArrayList(); + mode = mod; + hash = new HashMap(); + size_t = 0; + } + /*Regular peak, size, empty functions*/ + int peak() { + return heap.get(0); + } + + int size() { + return size_t; + } + + Boolean empty() { + return (heap.size() == 0); + } + // Basis of heap + int parent(int id) { + if (id == 0) { + return -1; + } + return (id - 1) / 2; + } + // Basis of heap. Our heap is base indxe = 0 + int lson(int id) { + return id * 2 + 1; + } + // Basis of heap. Our heap is base indxe = 0 + int rson(int id) { + return id * 2 + 2; + } + // Basis of heap. + //If min heap, parent < left/right child + //If max heap, parent > left/right child + boolean comparesmall(int a, int b) { + if (a <= b) { + if (mode == "min") + return true; + else + return false; + } else { + if (mode == "min") + return false; + else + return true; + } + + } + //swap value in heap based the 2 ids + //based on value, create new node in hashmap. + void swap(int idA, int idB) { + int valA = heap.get(idA); + int valB = heap.get(idB); + + int numA = hash.get(valA).num; + int numB = hash.get(valB).num; + hash.put(valB, new Node(idA, numB)); + hash.put(valA, new Node(idB, numA)); + heap.set(idA, valB); + heap.set(idB, valA); + } + + //Similar to delete, but only delete element at index==0, and return the value + Integer poll() { + size_t--; + Integer now = heap.get(0); + Node hashnow = hash.get(now); + if (hashnow.num == 1) { + swap(0, heap.size() - 1); + hash.remove(now); + heap.remove(heap.size() - 1); + if (heap.size() > 0) { + siftdown(0); + } + } else { + hash.put(now, new Node(0, hashnow.num - 1)); + } + return now; + } + //Add + //If exist, count++ in hashmap + //If not exited, add to tail, then sfitup + void add(int now) { + size_t++; + if (hash.containsKey(now)) { + Node hashnow = hash.get(now); + hash.put(now, new Node(hashnow.id, hashnow.num + 1)); + + } else { + heap.add(now); + hash.put(now, new Node(heap.size() - 1, 1)); + } + + siftup(heap.size() - 1); + } + //Remove node + //If not last one, count-- from the hashMap + //If last one, move it to tail of the structure, and delete it. + //When the id is not tail (note, the id is already attached with new values after swap), then siftup and siftdown to sort all ids + void delete(int now) { + size_t--; + ; + Node hashnow = hash.get(now); + int id = hashnow.id; + int num = hashnow.num; + if (hashnow.num == 1) { + + swap(id, heap.size() - 1); + hash.remove(now); + heap.remove(heap.size() - 1); + if (heap.size() > id) { + siftup(id); + siftdown(id); + } + } else { + hash.put(now, new Node(id, num - 1)); + } + } + //If the target id and its parent do not comply the heap structure, siftup. + void siftup(int id) { + while (parent(id) > -1) { + int parentId = parent(id); + if (comparesmall(heap.get(parentId), heap.get(id)) == true) { + break; + } else { + swap(id, parentId); + } + id = parentId; + } + } + //If the target id and its children do not comply with the heap structure, siftdown + void siftdown(int id) { + while (lson(id) < heap.size()) { + int leftId = lson(id); + int rightId = rson(id); + int son; + if (rightId >= heap.size() || (comparesmall(heap.get(leftId), heap.get(rightId)) == true)) { + son = leftId; + } else { + son = rightId; + } + if (comparesmall(heap.get(id), heap.get(son)) == true) { + break; + } else { + swap(id, son); + } + id = son; + } + } +} diff --git a/Others/old records/LintCode-Backup/Classical Binary Search.java b/Others/old records/LintCode-Backup/Classical Binary Search.java new file mode 100644 index 0000000..b4e7f42 --- /dev/null +++ b/Others/old records/LintCode-Backup/Classical Binary Search.java @@ -0,0 +1,62 @@ +E + + while: start + 1 < end + mid = start + (end - start) / 2; + 末尾double check start, end. + + +``` +/* +Find any position of a target number in a sorted array. +Return -1 if target does not exist. + +Example +Given [1, 2, 2, 4, 5, 5]. + +For target = 2, return 1 or 2. + +For target = 5, return 4 or 5. + +For target = 6, return -1. + +Challenge +O(logn) time + +Tags Expand +Binary Search +*/ + +/* +Thoughts: classic +start,mid,end +*/ +public class Solution { + /** + * @param A an integer array sorted in ascending order + * @param target an integer + * @return an integer + */ + public int findPosition(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + int start = 0; + int end = A.length - 1; + int mid; + while(start + 1 < end) { + mid = start + (end - start) / 2; + if (target == A[mid]) { + return mid; + } else if (target > A[mid]) { + start = mid; + } else { + end = mid; + } + }//end while + if (A[start] == target || A[end] == target) { + return A[start] == target ? start : end; + } + return -1; + } +} +``` diff --git a/Others/old records/LintCode-Backup/Climbing Stairs.java b/Others/old records/LintCode-Backup/Climbing Stairs.java new file mode 100644 index 0000000..254d0b9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Climbing Stairs.java @@ -0,0 +1,44 @@ +/* +40% Accepted +You are climbing a stair case. It takes n steps to reach to the top. + +Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? + +Example +Tags Expand + +Thinking process: +State: at i level, f[i] is the ways to climb to i position. +Function: f[i] = f[i-1] + f[i-2]. + f[i] is constructed from 2 branches: + Last step is 1 from f[i-1] + Last step is 2 from f[i-2] + This idea can be presented using a tree. However we don’t need to do recursive. We just need to use two pointers to withhold 2 level’s values. +Init: The for loop starts at level2, so before level 2 there are 2 init states: + f[0] == 1. This means we jump 2 steps from level0 to level2. + f[i] == 1. This means we jump 1 steps to level1, then jump another step to level2 +Answer: f[n] +*/ + +public class Solution { + /** + * @param n: An integer + * @return: An integer + */ + public int climbStairs(int n) { + if (n <= 2) { + return n; + } + int last = 1; //Init f[1] + int lastlast = 1; //Init f[0] + int now = 0; + for (int i = 2; i <= n; i++) { //Start from level2 + now = last + lastlast; + lastlast = last; + last = now; + } + return now; + } +} + + diff --git a/Others/old records/LintCode-Backup/Clone Graph.java b/Others/old records/LintCode-Backup/Clone Graph.java new file mode 100644 index 0000000..eeaabe3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Clone Graph.java @@ -0,0 +1,136 @@ +/* +Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. + + +OJ's undirected graph serialization: +Nodes are labeled uniquely. + +We use # as a separator for each node, and , as a separator for node label and each neighbor of the node. +As an example, consider the serialized graph {0,1,2#1,2#2,2}. + +The graph has a total of three nodes, and therefore contains three parts as separated by #. + +First node is labeled as 0. Connect node 0 to both nodes 1 and 2. +Second node is labeled as 1. Connect node 1 to node 2. +Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle. +Visually, the graph looks like the following: + + 1 + / \ + / \ + 0 --- 2 + / \ + \_/ +Hide Tags Depth-first Search Breadth-first Search Graph + + +*/ + +/* + //NEED TO RUN THIS ON LINT + Thoughts: 12.12.2015 + The original thoughs of using ArrayList, and using a index to track of which node has not been visited. + It's alright, but it uses extra space, and basically copie all nodes again. + It's similar to using a queue. + At the end, it's doing O(m * n) + Maybe can improve this. + + Need a queue and process each element. and a hashmap to track duplicates. + 1. make sure the node is no duplicate + 2. make sure to all all child + + border: case: node == nul, or node has not child, return a new instance of it'self? + +*/ + +public class Solution { + public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { + if (node == null || node.neighbors.size() == 0) { + return node; + } + + HashMap map = + new HashMap(); + Queue queue = new LinkedList(); + + queue.offer(node); + //process each node + while (!queue.isEmpty()) { + UndirectedGraphNode curr = queue.poll(); + UndirectedGraphNode newNode; + if (!map.containsKey(curr)) { + map.put(curr, new UndirectedGraphNode(curr.label)); + } + UndirectedGraphNode newNode = map.get(curr); + //Add neighbors for each node + for (UndirectedGraphNode neighbor : curr.neighbors) { + UndirectedGraphNode newNeighbor; + if (!map.containsKey(neighbor)) { + map.put(neighbor, new UndirectedGraphNode(neighbor.label)); + } + newNeighbor = map.get(neighbor); + + newNode.neighbors.add(newNeighbor); + }//end for + + }//end while + + return map.get(node); + } +} + + + +/* + + +Thinking process: +1. Clone all nodes available: using HashMap to go through all possible query. No duplicates added using HashMap. + HashMap map has the list of all new nodes. No neighbors added yet + = + At same time, the arrayList nodes has all original nodes(with neighbors) in Breadth-first order. +2. Add neighbor for nodes in map: + - Locate the 'newNode' from map by using the key: the original node + - loop through the original node's neighbor size + - use original neighbor as key to get the new neighbor instance from map + - add this new neighbor instance to the neighbor list of 'newNode' +*/ +/** + * Definition for undirected graph. + * class UndirectedGraphNode { + * int label; + * List neighbors; + * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } + * }; + */ +public class Solution { + public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { + if (node == null) { + return node; + } + ArrayList nodes = new ArrayList(); + nodes.add(node); + HashMap map = new HashMap(); + map.put(node, new UndirectedGraphNode(node.label)); + int start = 0; + //Clone nodes without neighbors: + while (start < nodes.size()) { + List neighbors = nodes.get(start++).neighbors; + for (int i = 0; i < neighbors.size(); i++) { + if (!map.containsKey(neighbors.get(i))) { + map.put(neighbors.get(i), new UndirectedGraphNode(neighbors.get(i).label)); + nodes.add(neighbors.get(i)); + } + } + } + // Clone neighbors: + for (int i = 0; i < nodes.size(); i++) { + UndirectedGraphNode newNode = map.get(nodes.get(i)); + for (int j = 0; j < nodes.get(i).neighbors.size(); j++) { + newNode.neighbors.add(map.get(nodes.get(i).neighbors.get(j))); + } + } + return map.get(node); + } +} + diff --git a/Others/old records/LintCode-Backup/Closest Number in Sorted Array.java b/Others/old records/LintCode-Backup/Closest Number in Sorted Array.java new file mode 100644 index 0000000..29ab136 --- /dev/null +++ b/Others/old records/LintCode-Backup/Closest Number in Sorted Array.java @@ -0,0 +1,65 @@ +Binary search. 考虑mid-1, mid+1. +一旦没有mid = target.index。 那么target最终就narrow down在(mid-1,mid) 或者(mid,mid+1) +``` +/* +Given a target number and an integer array A sorted in ascending order, find the index i in A such that A[i] is closest to the given target. + +Return -1 if there is no element in the array. + +Example +Given [1, 2, 3] and target = 2, return 1. + +Given [1, 4, 6] and target = 3, return 1. + +Given [1, 4, 6] and target = 5, return 1 or 2. + +Given [1, 3, 3, 4] and target = 2, return 0 or 1 or 2. + +Note +There can be duplicate elements in the array, and we can return any of the indices with same value. + +Challenge +O(logn) time complexity. + +Tags Expand +Binary Search +*/ +/* + Thoughts: + Do binary search. + Check the state of A[mid] < target < A[mid + 1] or A[mid - 1] < target < A[mid] + return the index that creates smallest diff. +*/ + +public class Solution { + /** + * @param A an integer array sorted in ascending order + * @param target an integer + * @return an integer + */ + public int closestNumber(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + int start = 0; + int end = A.length - 1; + int mid; + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A[mid] == target) { + return mid; + } else if (mid - 1 >= 0 && A[mid - 1] <= target && target < A[mid]) { + return (target - A[mid - 1]) < (A[mid] - target) ? (mid - 1) : mid; + } else if (mid + 1 < A.length && A[mid] < target && target <= A[mid + 1]) { + return (target - A[mid]) < (A[mid + 1] - target) ? mid : mid + 1; + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + return (target - A[start]) < (A[end] - target) ? start : end; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Coins in a Line.java b/Others/old records/LintCode-Backup/Coins in a Line.java new file mode 100644 index 0000000..d7adc09 --- /dev/null +++ b/Others/old records/LintCode-Backup/Coins in a Line.java @@ -0,0 +1,95 @@ +这题没见过的时候,要分析分析。分析出来了些个DP解决。 +However, 分析过后简直屌炸天。一个 n%3就解决了。纯粹math. +``` +/* +There are n coins in a line. Two players take turns to take one or two coins from right side until there are no more coins left. The player who take the last coin wins. + +Could you please decide the first play will win or lose? + +Example +n = 1, return true. + +n = 2, return true. + +n = 3, return false. + +n = 4, return true. + +n = 5, return true. + +Challenge +O(n) time and O(1) memory + +Tags Expand +Greedy Dynamic Programming Array Game Theory +*/ + +/* +Thoughts: +Clarify: '1st play will win' means: if play properly, +1st play will surely have a way to win that 2nd play can't beat. +Make dp[i]: the result when n = i. +fn: +Think back a step, state-1: +When it's play1's turn, there might be 1 or 2 coins left so he can win. so -1, or -2. +THink back a 2nd step, state-2: +Play2 take 1 or 2 to get into state-1. play2 may take 1 or 2 coins. so again, -1 or -2. + +So consider i-1, i-2, i-3, or i-4. Note, the next stemp would be for play2, then play1. +However, if left are 1,2 coins for play2, play2 wins; if left are 4 coins, play2 wins; only when left are 3 coins, play2 will surely lose, so play1 win. +Therefore, there is just 1 case to consider: if left are 3 coins, and it's play2's turn, then play1 surely wins. +so fn: +dp[i] = dp[i-3] + +Init: +dp[0] = false; dp[1], dp[2] = tru; dp[3] = false; + +Result: +dp[n] + +*/ +/* O(n) time and O(n)space.*/ +public class Solution { + /** + * @param n: an integer + * @return: a boolean which equals to true if the first player will win + */ + public boolean firstWillWin(int n) { + if (n <= 0) { + return false; + } + if (n <= 2) { + return true; + } + boolean[] dp = new boolean[n + 1]; + dp[1] = true; + dp[2] = true; + dp[3] = false; + for (int i = 4; i <= n; i++) { + dp[i] = dp[i - 3]; + } + return dp[n]; + } +} + +/* + O(1) time and O(1)space. + Base on the analysis in 1st attempt: + As long as it's not product of 3 + However, this is pretty ... math. Not quite useful to test coding ability. +*/ + +public class Solution { + /** + * @param n: an integer + * @return: a boolean which equals to true if the first player will win + */ + public boolean firstWillWin(int n) { + if (n <= 0) { + return false; + } + return n % 3 != 0; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Combination Sum II.java b/Others/old records/LintCode-Backup/Combination Sum II.java new file mode 100644 index 0000000..001b450 --- /dev/null +++ b/Others/old records/LintCode-Backup/Combination Sum II.java @@ -0,0 +1,76 @@ +确保Helper是用i+1,下一层的数字。 + +``` +/* +Given a collection of candidate numbers (C) and a target number (T), +find all unique combinations in C where the candidate numbers sums to T. + +Each number in C may only be used once in the combination. + +Note +All numbers (including target) will be positive integers. +Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak). +The solution set must not contain duplicate combinations. +Example +For example, given candidate set 10,1,6,7,2,1,5 and target 8, + +A solution set is: + +[1,7] + +[1,2,5] + +[2,6] + +[1,1,6] + +Tags Expand +Backtracking Array + +Thinking process: +Exact same idea as in Combination Sum I. The difference is, +cannot reuse the current index in nums. Instead, in helper() function, use index of i + 1 +*/ +public class Solution { + /** + * @param num: Given the candidate numbers + * @param target: Given the target number + * @return: All the combinations that sum to target + */ + public List> combinationSum2(int[] num, int target) { + List> rst = new ArrayList>(); + List list = new ArrayList(); + if (num == null || num.length == 0 || target < 0) { + return rst; + } + Arrays.sort(num); + helper(rst, list, num, target, 0, 0); + return rst; + } + public void helper(List> rst, List list, + int[] num, int target, int sum, int start) { + if (sum == target) { + rst.add(new ArrayList(list)); + return; + } else if (sum > target) {//Stop if greater than target + return; + } + int prev = -1;//Repeat detection + for (int i = start; i < num.length; i++) { + if (prev != -1 && prev == num[i]) { + continue; + } + list.add(num[i]); + sum += num[i]; + helper(rst, list, num, target, sum, i + 1); + //Back track: + sum -= num[i]; + list.remove(list.size() - 1); + //Repeat Detection + prev = num[i]; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Combination Sum.java b/Others/old records/LintCode-Backup/Combination Sum.java new file mode 100644 index 0000000..0566a71 --- /dev/null +++ b/Others/old records/LintCode-Backup/Combination Sum.java @@ -0,0 +1,77 @@ +递归,backtracking. 非常normal。 +记得求sum时候也pass 一个sum进去,backtracking一下sum也,这样就不必每次都sum the list了。 +``` +/* +Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. + +The same repeated number may be chosen from C unlimited number of times. + + + +For example, given candidate set 2,3,6,7 and target 7, +A solution set is: +[7] +[2, 2, 3] + +Note +All numbers (including target) will be positive integers. +Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak). +The solution set must not contain duplicate combinations. +Example +given candidate set 2,3,6,7 and target 7, +A solution set is: +[7] +[2, 2, 3] + +Tags Expand +Backtracking Array + +Thinking process: +Similar to 'Combination' problem, do back-tracking with ability to repeat itself at index i. +In order to stop duplicates of result entry, use a 'prev' tracker to 'continue' if a value is repeating at any index. Skip repeating integers because we've already allow unlimited # of same integer in one single solution. (IMPORTANT: will have to sort the int[] in order to detect the duplicates) +In particular, I pass a 'sum' to compare with 'target' (want to have sum == target). Some solution prefer to use 'target - someVlaue' == 0 to find solution. +*/ + +public class Solution { + /** + * @param candidates: A list of integers + * @param target:An integer + * @return: A list of lists of integers + */ + public List> combinationSum(int[] num, int target) { + List> rst = new ArrayList>(); + List list = new ArrayList(); + if (num == null || num.length == 0 || target < 0) { + return rst; + } + Arrays.sort(num); + helper(rst, list, num, target, 0, 0); + return rst; + } + public void helper(List> rst, List list, + int[] num, int target, int sum, int start) { + if (sum == target) { + rst.add(new ArrayList(list)); + return; + } else if (sum > target) {//Stop if greater than target + return; + } + int prev = -1;//Repeat detection + for (int i = start; i < num.length; i++) { + if (prev != -1 && prev == num[i]) { + continue; + } + list.add(num[i]); + sum += num[i]; + helper(rst, list, num, target, sum, i); + //Back track: + sum -= num[i]; + list.remove(list.size() - 1); + //Repeat Detection + prev = num[i]; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Combinations.java b/Others/old records/LintCode-Backup/Combinations.java new file mode 100644 index 0000000..2286e9b --- /dev/null +++ b/Others/old records/LintCode-Backup/Combinations.java @@ -0,0 +1,44 @@ +/* +Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. + +Example +For example, +If n = 4 and k = 2, a solution is: +[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]] +Tags Expand +Backtracking Array + +Thinking process: +Use a helper method to perform recursive backtracking:add an element to next-level recursive call, and remote the entry after the recursive call. +Note: When 'new' something, cannot use 'List' because it's a abstract class. Need to new 'ArrayList' +*/ + +public class Solution { + /** + * @param n: Given the range of numbers + * @param k: Given the numbers of combinations + * @return: All the combinations of k numbers out of 1..n + */ + public List> combine(int n, int k) { + List> rst = new ArrayList>(); + if (n <= 0 || k <= 0) { + return rst; + } + List solution = new ArrayList(); + helper(rst, solution, n, k, 1);// Start == 1 because we want 1 ~ n in this problem + return rst; + } + public void helper(List> rst, + List solution, int n, int k, int start) { + if (solution.size() == k) { + rst.add(new ArrayList(solution)); + return; + } + for (int i = start; i <= n; i++) {// <=n because we want 1 ~ n in this problem + solution.add(i); + helper(rst, solution, n, k, i + 1); + solution.remove(solution.size() - 1); //Back-track + } + } +} + diff --git a/Others/old records/LintCode-Backup/Compare Strings.java b/Others/old records/LintCode-Backup/Compare Strings.java new file mode 100644 index 0000000..1cf9b3a --- /dev/null +++ b/Others/old records/LintCode-Backup/Compare Strings.java @@ -0,0 +1,44 @@ +/* +Compare two strings A and B, determine whether A contains all of the characters in B. + +The characters in string A and B are all Upper Case letters. + +Example +For A = "ABCD", B = "ABC", return true. + +For A = "ABCD" B = "AABC", return false. + +Tags Expand +Basic Implementation String LintCode Copyright + +Thinking process: +Count the number of occurance for StringA. +Count the number of occurance for StringB. +Check if all of StringB's char# <= StringA's char# at each index. +*/ + +public class Solution { + /** + * @param A : A string includes Upper Case letters + * @param B : A string includes Upper Case letter + * @return : if string A contains all of the characters in B return true else return false + */ + public boolean compareStrings(String A, String B) { + if (A == null || B == null || A.length() < B.length()) { + return false; + } + int[] countA = new int[26]; + int[] countB = new int[26]; + for (int i = 0; i < A.length(); i++) { + countA[A.charAt(i) - 'A']++; + } + for (int i = 0; i < B.length(); i++) { + countB[B.charAt(i) - 'A']++; + if (countB[B.charAt(i) - 'A'] > countA[B.charAt(i) - 'A']) { + return false; + } + } + return true; + } +} + diff --git a/Others/old records/LintCode-Backup/Complete Binary Tree.java b/Others/old records/LintCode-Backup/Complete Binary Tree.java new file mode 100644 index 0000000..03fbba4 --- /dev/null +++ b/Others/old records/LintCode-Backup/Complete Binary Tree.java @@ -0,0 +1,88 @@ +Use a flag . 当出现了第一次有 null children的node的时候, +说明complete tree的最低level出现了。 +自此以后,再不该有node再有child, queue后面出现的node应该左右孩子都是null. + +用BFS +``` +/* +Check a binary tree is completed or not. A complete binary tree is not binary tree that every level is completed filled except the deepest level. In the deepest level, all nodes must be as left as possible. See more definition + +Have you met this question in a real interview? Yes +Example + 1 + / \ + 2 3 + / +4 +is a complete binary. + + 1 + / \ + 2 3 + \ + 4 +is not a complete binary. + +Challenge +Do it in O(n) time + +Tags Expand +Binary Tree +*/ + +/* + Thoughts: + Do a BFS. + Once null occur, all the rest following it has to be null +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + +public class Solution { + /** + * @param root, the root of binary tree. + * @return true if it is a complete binary tree, or false. + */ + public boolean isComplete(TreeNode root) { + if (root == null) { + return true; + } + + Queue queue = new LinkedList(); + queue.offer(root); + boolean flag = false; + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (flag && (node.left != null || node.right != null)) { + return false; + } + if (node.left == null && node.right != null) { + return false; + } else if (node.left == null || node.right == null) { + flag = true; + } + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } + + return true; + } + + +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Postorder Traversal.java b/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Postorder Traversal.java new file mode 100644 index 0000000..fcdb29a --- /dev/null +++ b/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Postorder Traversal.java @@ -0,0 +1,87 @@ +/* +Given inorder and postorder traversal of a tree, construct the binary tree. + +Note +You may assume that duplicates do not exist in the tree. + +Example +Given inorder [1,2,3] and postorder [1,3,2] + +return a tree + + 2 + / \ +1 3 + + +Tags Expand +Binary Tree + +Thinking process: +Know that the last element of PostOrder array is the root of the Binary tree. +Find this root from the InOrder array, which will be the middle point. The front-part of the inorder array will be left-tree, the end-part of the inorder array will be the right-tree. +Trick part: +1. Need a helper function to perfrom divide/conquer. +2. Need to be careful when cutting the inorder and postorder array. + For inorder array, left array: (instart, middlePosition -1), right array: (middlePosition + 1, inend) + For postorder array: when cutting, we know the very last node is cut off already, so we just need to evenly split the rest array. + left array(postStart, postStart + (middlePosition - instart) - 1). + Note: (middlePositon - instart) means the length of the left-array/size of the left-tree + However, postStart + left-array-length exceed 1 over postorder-left-tree, hence minus 1 here. + right array(postStart + (middlePosition - instart), postend - 1) + Note: postStart + left-tree-length is exactly the starting point of the post-right-array. + Because the ending element is cut off previously to serve as root, we need to do (postend - 1) for correct postorder-right-tree. + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + +public class Solution { + /** + *@param inorder : A list of integers that inorder traversal of a tree + *@param postorder : A list of integers that postorder traversal of a tree + *@return : Root of a tree + */ + public TreeNode buildTree(int[] inorder, int[] postorder) { + if (inorder.length != postorder.length) { + return null; + } + return buildTreeHelper(inorder, 0, inorder.length - 1, + postorder, 0, postorder.length - 1); + } + + public TreeNode buildTreeHelper(int[] inorder, int inStart, int inEnd, + int[] postorder, int postStart, int postEnd){ + if (inStart > inEnd) { + return null; + } + TreeNode root = new TreeNode(postorder[postEnd]); + int mid = findMid(inorder, inStart, inEnd, postorder[postEnd]); + root.left = buildTreeHelper(inorder, inStart, mid - 1, + postorder, postStart, postStart + (mid - inStart) - 1); + root.right = buildTreeHelper(inorder, mid + 1, inEnd, + postorder, postStart + (mid - inStart), postEnd - 1); + return root; + } + + public int findMid(int[] arr, int start, int end, int key) { + for (int i = start; i <= end; i++) { + if (arr[i] == key) { + return i; + } + } + return -1; + } +} + diff --git a/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Preorder Traversal.java b/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Preorder Traversal.java new file mode 100644 index 0000000..3026d0d --- /dev/null +++ b/Others/old records/LintCode-Backup/Construct Binary Tree from Inorder and Preorder Traversal.java @@ -0,0 +1,79 @@ +/* +Given preorder and inorder traversal of a tree, construct the binary tree. + +Note +You may assume that duplicates do not exist in the tree. + +Example +Given inorder [1,2,3] and preorder [2,1,3] + +return a tree + + 2 + + / \ + +1 3 + +Tags Expand +Binary Tree + +Thinking process: +See 'Construct tree from inorder + postorder' as example. +This problem uses divide and conquer idea as well. +For preorder: the front node is the root of the tree. +For inorder: find the root in the middle of the array, then the left-side is left-tree, and the right-side is the right-tree. +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + + +public class Solution { + /** + *@param preorder : A list of integers that preorder traversal of a tree + *@param inorder : A list of integers that inorder traversal of a tree + *@return : Root of a tree + */ + public TreeNode buildTree(int[] preorder, int[] inorder) { + if (preorder.length != inorder.length) { + return null; + } + return buildTreeHelper(inorder, 0, inorder.length - 1, + preorder, 0, preorder.length - 1); + } + + public TreeNode buildTreeHelper(int[] inorder, int inStart, int inEnd, + int[] preorder, int preStart, int preEnd) { + if (inStart > inEnd) { + return null; + } + TreeNode root = new TreeNode(preorder[preStart]); + int mid = findMid(inorder, inStart, inEnd, preorder[preStart]); + + root.left = buildTreeHelper(inorder, inStart, mid - 1, + preorder, preStart + 1, preStart + (mid - inStart)); + root.right = buildTreeHelper(inorder, mid + 1, inEnd, + preorder, preStart + (mid - inStart) + 1, preEnd); + return root; + } + + public int findMid(int[] arr, int start, int end, int key) { + for (int i = start; i <= end; i++) { + if (arr[i] == key) { + return i; + } + } + return -1; + } +} + diff --git a/Others/old records/LintCode-Backup/Container With Most Water.java b/Others/old records/LintCode-Backup/Container With Most Water.java new file mode 100644 index 0000000..0b0f55f --- /dev/null +++ b/Others/old records/LintCode-Backup/Container With Most Water.java @@ -0,0 +1,51 @@ +类似木桶理论。盛水的最高取决于最低的那面墙。 +左右两墙,往中间跑动。 +另,若一面墙已经小于另外一面,就要移动,换掉矮墙(可能下一面更高,或更低);但决不能换掉当下的高墙,因为低墙已经limit的盛水的上限,若高墙移动,导致两墙之间距离减少,就注定水量更少了。(弄啥来,不能缺心眼啊) +``` +/* +Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. + +Example +Given [1,3,2], the max area of the container is 2. + +Note +You may not slant the container. + +Tags Expand +Two Pointers Array +*/ + +/* +Thoughts: +Start from 2 sides with 2 pointers, use those as 2 walls. + +Height of water is limited by the lower wall. For example, left wall < right wall, width = right.x - left.x + Now, if we move right wall: right--, then width = width-1, and the whole block is still limited by the lower left wall. So, this is not a good move. + Instead, when left wall < right wall, we move left++. + On the other hand, if lett wall > right wall, right--. +*/ +public class Solution { + /** + * @param heights: an array of integers + * @return: an integer + */ + public int maxArea(int[] heights) { + if (heights == null || heights.length == 0) { + return 0; + } + int left = 0; + int right = heights.length - 1; + int maxWater = Integer.MIN_VALUE; + while (left < right) { + maxWater = Math.max(maxWater, (right-left) * (heights[left] < heights[right] ? heights[left] : heights[right])); + if (heights[left] < heights[right]) { + left++; + } else { + right--; + } + } + return maxWater; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Convert Binary Search Tree to Doubly Linked List.java b/Others/old records/LintCode-Backup/Convert Binary Search Tree to Doubly Linked List.java new file mode 100644 index 0000000..2efc30d --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Binary Search Tree to Doubly Linked List.java @@ -0,0 +1,114 @@ +注意inorder traversal在check right node的事后, +不论right == null or != null, 每次都要强行move to right. + +如果不node = node.right, +很可能发生窘境: +node alays = stack.top(), 然后stack.top()一直是一开始把left 全部遍历的内容。所以就会infinite loop, 永远在左边上下上下。 +``` +/* + +Convert a binary search tree to doubly linked list with in-order traversal. + +Have you met this question in a real interview? Yes +Example +Given a binary search tree: + + 4 + / \ + 2 5 + / \ +1 3 +return 1<->2<->3<->4<->5 + +Tags Expand +Linked List +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + * Definition for Doubly-ListNode. + * public class DoublyListNode { + * int val; + * DoublyListNode next, prev; + * DoublyListNode(int val) { + * this.val = val; + * this.next = this.prev = null; + * } + * } + */ + + +/* + Thoughts: + Inorder with 1 stack: peek add left till end, pop and add, then push right node. + + Everytime when pop out a node and add, make it a new boubllistnode + dNode.next = curr + curr.pre = dNode.next + dNode = dNode.next + + boarder case: if null, return a null. +*/ +public class Solution { + /** + * @param root: The root of tree + * @return: the head of doubly list node + */ + public DoublyListNode bstToDoublyList(TreeNode root) { + if (root == null) { + return null; + } + //Init stack + Stack stack = new Stack(); + TreeNode node = root; + stack.push(node); + //Create DoublyListNode header + DoublyListNode dummy = new DoublyListNode(0); + DoublyListNode dNode = dummy; + + + while(!stack.isEmpty()) { + while (node != null && node.left != null) { + stack.push(node.left); + node = node.left; + } + //add node + node = stack.pop(); + DoublyListNode curr = new DoublyListNode(node.val); + dNode.next = curr; + curr.prev = dNode; + dNode = dNode.next; + + //check right node and add to stack + node = node.right; + if (node != null) { + stack.push(node); + } + } + + return dummy.next; + + } +} + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Convert Expression to Polish Notation.java b/Others/old records/LintCode-Backup/Convert Expression to Polish Notation.java new file mode 100644 index 0000000..7046567 --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Expression to Polish Notation.java @@ -0,0 +1,117 @@ +还是Expression Tree (Min-Tree). +根据题意,Tree出来以后,来个Pre-order-traversal. +``` +/* +Given an expression string array, return the Polish notation of this expression. (remove the parentheses) + +Have you met this question in a real interview? Yes +Example +For the expression [(5 − 6) * 7] (which represented by ["(", "5", "−", "6", ")", "*", "7"]), the corresponding polish notation is [* - 5 6 7] (which the return value should be ["*", "−", "5", "6", "7"]). + +Clarification +Definition of Polish Notation: + +http://en.wikipedia.org/wiki/Polish_notation +http://baike.baidu.com/view/7857952.htm +Tags Expand +LintCode Copyright Stack +*/ + +/* +Thoughts: +Build the expression tree, and do a pre-order-traversal, and record all nodes in the array list. + +Let's practice expression tree build again. +*/ + +public class Solution { + class TreeNode { + String s; + int val; + TreeNode left; + TreeNode right; + public TreeNode(int val, String s) { + this.val = val; + this.s = s; + this.left = null; + this.right = null; + } + } + + public TreeNode build(String[] expression) { + if (expression == null || expression.length == 0) { + return null; + } + Stack stack = new Stack(); + int base = 0; + int val = 0; + + for (int i = 0; i < expression.length; i++) { + if (expression[i].equals("(")) { + base += 10; + continue; + } + if (expression[i].equals(")")) { + base -= 10; + continue; + } + val = getWeight(base, expression[i]); + TreeNode node = new TreeNode(val, expression[i]); + while (!stack.isEmpty() && node.val <= stack.peek().val) { + node.left = stack.pop(); + } + if (!stack.isEmpty()) { + stack.peek().right = node; + } + stack.push(node); + } + if (stack.isEmpty()) { + return null; + } + TreeNode rst = stack.pop(); + while (!stack.isEmpty()) { + rst = stack.pop(); + } + return rst; + } + + public int getWeight(int base, String s) { + if (s.equals("+") || s.equals("-")) { + return base + 1; + } + if (s.equals("*") || s.equals("/")) { + return base + 2; + } + return Integer.MAX_VALUE; + } + + /** + * @param expression: A string array + * @return: The Polish notation of this expression + */ + public ArrayList convertToPN(String[] expression) { + ArrayList rst = new ArrayList(); + if (expression == null || expression.length == 0) { + return rst; + } + TreeNode root = build(expression); + preTraversal(rst, root); + + return rst; + } + + public void preTraversal(ArrayList rst, TreeNode node){ + if (node == null) { + return; + } + if (node.left == null && node.right == null) { + rst.add(node.s); + return; + } + rst.add(node.s); + preTraversal(rst, node.left); + preTraversal(rst, node.right); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Convert Expression to Reverse Polish Notation.java b/Others/old records/LintCode-Backup/Convert Expression to Reverse Polish Notation.java new file mode 100644 index 0000000..6b0df9f --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Expression to Reverse Polish Notation.java @@ -0,0 +1,117 @@ +用build expression tree开头。 +这个里面把TreeNode就当做成我们需要的node,里面扩展成有left/right child的node. +这题,目的是建造tree,然后来个post-traversal就行了。 +``` +/* +Given an expression string array, return the Reverse Polish notation of this expression. (remove the parentheses) + +Example +For the expression [3 - 4 + 5] (which denote by ["3", "-", "4", "+", "5"]), return [3 4 - 5 +] (which denote by ["3", "4", "-", "5", "+"]) + +Tags: +LintCode Copyright Stack +*/ + +/* +Thought: +Reverse Polish notation: +Put operator after operands. + +First build the tree, then do post-traversal. +*/ + + +public class Solution { + /***** build expression tree******/ + class TreeNode { + int val; + String s; + TreeNode left; + TreeNode right; + public TreeNode(int val, String s) { + this.val = val; + this.s = s; + this.left = null; + this.right = null; + } + } + public TreeNode build(String[] expression) { + Stack stack = new Stack(); + int base = 0; + int val = 0; + + for (int i = 0; i < expression.length; i++) { + if (expression[i].equals("(")) { + base += 10; + continue; + } + if (expression[i].equals(")")) { + base -= 10; + continue; + } + val = getWeight(base, expression[i]); + + TreeNode node = new TreeNode(val, expression[i]); + while (!stack.isEmpty() && node.val <= stack.peek().val) { + node.left = stack.pop(); + } + if (!stack.isEmpty()) { + stack.peek().right = node; + } + stack.push(node); + + } + if (stack.isEmpty()) { + return null; + } + TreeNode rst = stack.pop(); + while (!stack.isEmpty()) { + rst = stack.pop(); + } + return rst; + } + //Calculate weight for characters + public int getWeight(int base, String s) { + if (s.equals("+") || s.equals("-")) { + return base + 1; + } + if (s.equals("*") || s.equals("/")) { + return base + 2; + } + return Integer.MAX_VALUE; + } + /***** build expression tree******/ + + + /** + * @param expression: A string array + * @return: The Reverse Polish notation of this expression + */ + public ArrayList convertToRPN(String[] expression) { + ArrayList rst = new ArrayList(); + if (expression == null || expression.length == 0) { + return rst; + } + TreeNode root = build(expression); + if (root == null) { + return rst; + } + postTraversal(rst, root); + return rst; + } + + public void postTraversal(ArrayList rst, TreeNode node){ + if (node == null) { + return; + } + if (node.left != null) { + postTraversal(rst, node.left); + } + if (node.right != null) { + postTraversal(rst, node.right); + } + rst.add(node.s); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Convert Integer A to Integer B.java b/Others/old records/LintCode-Backup/Convert Integer A to Integer B.java new file mode 100644 index 0000000..97b3974 --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Integer A to Integer B.java @@ -0,0 +1,34 @@ +/* +Determine the number of bits required to convert integer A to integer B + +Example +Given n = 31, m = 14,return 2 + +(31)10=(11111)2 + +(14)10=(01110)2 + +Tags Expand +Cracking The Coding Interview Bit Manipulation Binary Representation + +Thinking process: +Assume the integer is 32 bit. +XOR a and b, shift by 1 bit everytime -> want to check the XORed value at index 0 : just & 1 will do. +Count the above calculated result: how many bit difference do a and b have. +*/ + +class Solution { + /** + *@param a, b: Two integer + *return: An integer + */ + public static int bitSwapRequired(int a, int b) { + int count = 0; + for (int i = 0; i < 32; i++) { + count += (a ^ b) >> i & 1; + } + return count; + } +}; + + diff --git a/Others/old records/LintCode-Backup/Convert Sorted Array to Binary Search Tree With Minimal Height.java b/Others/old records/LintCode-Backup/Convert Sorted Array to Binary Search Tree With Minimal Height.java new file mode 100644 index 0000000..dccdbe6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Sorted Array to Binary Search Tree With Minimal Height.java @@ -0,0 +1,66 @@ +/* +Given a sorted (increasing order) array, Convert it to create a binary tree with minimal height. + +Have you met this question in a real interview? Yes +Example +Given [1,2,3,4,5,6,7], return + + 4 + / \ + 2 6 + / \ / \ +1 3 5 7 +Note +There may exist multiple valid solutions, return any of them. + +Tags Expand +Cracking The Coding Interview Recursion Binary Tree + +Thoughts: +1. Find middle point x. +2. All index before x, goes to left of the tree. Same apply to right tree + build sub array and pass alone: we can pass index start, end. + use parent node and pass along +3. Recur on left side array. + +*/ + + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param A: an integer array + * @return: a tree node + */ + public TreeNode sortedArrayToBST(int[] A) { + TreeNode root = null; + if (A == null || A.length == 0) { + return root; + } + root = helper(0, A.length - 1, A); + return root; + } + + public TreeNode helper(int start, int end, int[] A) { + if (start > end) { + return null; + } + //add middle node + int mid = start + (end - start)/2; + TreeNode node = new TreeNode(A[mid]); + //Split and append child + node.left = helper(start, mid - 1, A); + node.right = helper(mid + 1, end, A); + return node; + } +} diff --git a/Others/old records/LintCode-Backup/Convert Sorted List to Binary Search Tree.java b/Others/old records/LintCode-Backup/Convert Sorted List to Binary Search Tree.java new file mode 100644 index 0000000..3295e98 --- /dev/null +++ b/Others/old records/LintCode-Backup/Convert Sorted List to Binary Search Tree.java @@ -0,0 +1,84 @@ +Divide and Conquer + +找到mid。 +然后把root = mid.next + +然后开始sortedListToBST(mid.next.next); //后半段 +mid.next = null;//非常重要,要把后面拍过序的断掉 +sortedListToBST(head); //从头开始的前半段 + + +最后root.left, root.right merge一下。 + +``` +/* +Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. + +Example +Tags Expand +Recursion Linked List + +Thinking Process: +Find the middle point of the list. +Left of the mid will be left-tree, right of the mid node will be right-tree. + +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @return: a tree node + */ + public TreeNode sortedListToBST(ListNode head) { + if (head == null) { + return null; + } else if (head.next == null) { + return new TreeNode(head.val); + } + + ListNode mid = findMiddle(head); + TreeNode root = new TreeNode(mid.next.val); + TreeNode right = sortedListToBST(mid.next.next); + mid.next = null; + TreeNode left = sortedListToBST(head); + + root.left = left; + root.right = right; + return root; + } + + + public ListNode findMiddle(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Copy List with Random Pointer.java b/Others/old records/LintCode-Backup/Copy List with Random Pointer.java new file mode 100644 index 0000000..481895f --- /dev/null +++ b/Others/old records/LintCode-Backup/Copy List with Random Pointer.java @@ -0,0 +1,120 @@ +/* +31% Accepted +A linked list is given such that each node contains an additional random pointer +which could point to any node in the list or null. + +Return a deep copy of the list. + +Example +Tags Expand +Hash Table Linked List + +*/ + +/** + * Definition for singly-linked list with a random pointer. + * class RandomListNode { + * int label; + * RandomListNode next, random; + * RandomListNode(int x) { this.label = x; } + * }; + */ + +/* + Recap: 12.10.2015 + Iterative through the list. + Use a dummyHead and return dummyHead.next at the end. + In each iteration, check if Head is already exist, or make a new one + * use HashMap to mark if a node has been visited. + deep copy the random node of head as well. + + border case: if head == null, return null +*/ + + +public class Solution { + public RandomListNode copyRandomList(RandomListNode head) { + if (head == null) { + return null; + } + //creat node, used to link all nodes + RandomListNode dummy = new RandomListNode(0); + RandomListNode node = dummy; + RandomListNode newNode; + + //HashMap to mark node + HashMap map = new HashMap(); + + while(head != null) { + //process head. (we already know head!=null) + if (!map.containsKey(head)) { + map.put(head, new RandomListNode(head.label)); + } + newNode = map.get(head); + node.next = newNode; + //process head.random + if (head.random != null) { + if(!map.containsKey(head.random)) { + map.put(head.random, new RandomListNode(head.random.label)); + } + newNode = map.get(head.random); + node.next.random = newNode; + } + node = node.next; + head = head.next; + } + return dummy.next; + } +} + +/* +Thinking process: +1. Loop through the original list +2. Use a HashMap. User the old node as a key and new node as value. +3. Doesn't matter of the order of node that being added into the hashMap. + For example, node1 is added. + node1.random, which is node 99, will be added into hashMap right after node1. +4. During the loop: + If head exist in hashmap, get it; if not existed, create new node using head, add into hashMap + If head.random exist, get it; if not, add a new node using head.random. + +*/ +public class Solution { + /** + * @param head: The head of linked list with a random pointer. + * @return: A new head of a deep copy of the list. + */ + public RandomListNode copyRandomList(RandomListNode head) { + if (head == null) { + return null; + } + HashMap map = new HashMap(); + RandomListNode dummy = new RandomListNode(0); + RandomListNode pre = dummy; + RandomListNode newNode; + while (head != null) { + //Add new node + if (map.containsKey(head)) { + newNode = map.get(head); + } else { + newNode = new RandomListNode(head.label); + map.put(head, newNode); + } + //Add new node's random node + if (head.random != null) { + if (map.containsKey(head.random)) { + newNode.random = map.get(head.random); + } else { + newNode.random = new RandomListNode(head.random.label); + map.put(head.random, newNode.random); + } + } + //append and shift + pre.next = newNode; + pre = newNode; + head = head.next; + } + return dummy.next; + } +} + diff --git a/Others/old records/LintCode-Backup/Cosine Similarity.java b/Others/old records/LintCode-Backup/Cosine Similarity.java new file mode 100644 index 0000000..c71919e --- /dev/null +++ b/Others/old records/LintCode-Backup/Cosine Similarity.java @@ -0,0 +1,60 @@ +按题目意思,写出来就好了。 +``` +/* +Cosine similarity is a measure of similarity between two vectors of an inner product space that measures the cosine of the angle between them. +The cosine of 0° is 1, and it is less than 1 for any other angle. + +See wiki: Cosine Similarity + +Here is the formula: +http://www.lintcode.com/en/problem/cosine-similarity/# + +Given two vectors A and B with the same size, calculate the cosine similarity. + +Return 2.0000 if cosine similarity is invalid (for example A = [0] and B = [0]). + +Example +Given A = [1, 2, 3], B = [2, 3 ,4]. + +Return 0.9926. + +Given A = [0], B = [0]. + +Return 2.0000 + +*/ + +/* + Thoughts + Based on the given equation. Write up calculation + Check border. +*/ + +class Solution { + /** + * @param A: An integer array. + * @param B: An integer array. + * @return: Cosine similarity. + */ + public double cosineSimilarity(int[] A, int[] B) { + if (A == null || B == null || A.length == 0 || B.length == 0 || A.length != B.length) { + return 2; + } + + double sumProduct = 0; + double sumASq = 0; + double sumBSq = 0; + for (int i = 0; i < A.length; i++) { + sumProduct += A[i]*B[i]; + sumASq += A[i] * A[i]; + sumBSq += B[i] * B[i]; + } + if (sumASq == 0 && sumBSq == 0) { + return 2.0; + } + return sumProduct / (Math.sqrt(sumASq) * Math.sqrt(sumBSq)); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Count 1 in Binary.java b/Others/old records/LintCode-Backup/Count 1 in Binary.java new file mode 100644 index 0000000..1059210 --- /dev/null +++ b/Others/old records/LintCode-Backup/Count 1 in Binary.java @@ -0,0 +1,43 @@ +/* +Count how many 1 in binary representation of a 32-bit integer. + +Example +Given 32, return 1 + +Given 5, return 2 + +Given 1023, return 9 + +Challenge +If the integer is n bits with m 1 bits. Can you do it in O(m) time? + +Tags Expand +Binary Bit Manipulation + +Thoughts: +1. break string into char[] +2. convert char[] into integer using Character.getNumericValue() + +*/ + + + + +public class Solution { + /** + * @param num: an integer + * @return: an integer, the number of ones in num + */ + public int countOnes(int num) { + if (num < 0) { + return 0; + } + String bits = Integer.toBinaryString(num); + char[] bitArray = bits.toCharArray(); + int sum = 0; + for (int i = 0; i < bitArray.length; i++) { + sum += Character.getNumericValue(bitArray[i]); + } + return sum; + } +}; diff --git a/Others/old records/LintCode-Backup/Count and Say.java b/Others/old records/LintCode-Backup/Count and Say.java new file mode 100644 index 0000000..2d0fc5b --- /dev/null +++ b/Others/old records/LintCode-Backup/Count and Say.java @@ -0,0 +1,62 @@ +/* +The count-and-say sequence is the sequence of integers beginning as follows: + +1, 11, 21, 1211, 111221, ... + +1 is read off as "one 1" or 11. + +11 is read off as "two 1s" or 21. + +21 is read off as "one 2, then one 1" or 1211. + +Given an integer n, generate the nth sequence. + +Example +Given n = 5, return "111221". + +Note +The sequence of integers will be represented as a string. + +Tags Expand +String + + +1. Set up initial value '11' +2. use while loop to build on past variable +3. In each while loop case, break the string into charArray, count and name mark the type +4. In for loop: when different, append string (count+type); when same, count++. +*/ + + +public class Solution { + /** + * @param n the nth + * @return the nth sequence + */ + public String countAndSay(int n) { + if (n <= 1) { + return n + ""; + } + String str = "11"; + int ind = 2; + while (ind < n) { + StringBuffer sb = new StringBuffer(); + char[] arr = str.toCharArray(); + int count = 1; + int type = Character.getNumericValue(arr[0]); + for (int i = 1; i < arr.length; i++) { + if (arr[i] == arr[i - 1]) { + count++; + } else { + sb.append(count + "" + type); + type = Character.getNumericValue(arr[i]); + count = 1; + } + } + ind++; + sb.append(count + "" + type); + str = sb.toString(); + } + return str; + } +} diff --git a/Others/old records/LintCode-Backup/Count of Smaller Number before itself.java b/Others/old records/LintCode-Backup/Count of Smaller Number before itself.java new file mode 100644 index 0000000..1d0b9a8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Count of Smaller Number before itself.java @@ -0,0 +1,120 @@ +与Count of Smaller Number非常类似。 +Trick: 先Query,再modify. +每次Query时候,A[i]都还没有加入到Segment Tree 里面,而A[i+1...etc]自然也还没有加进去。 +那么就自然是coutning smaller number before itself. +刁钻啊! + +另外注意: +在modify里面:多Check了root.start <= index 和 index <= root.end。 过去都忽略了。以后可以把这个也写上。 +(其实是Make sense的,就是更加严格地check了index再 root.left 或者 root.right里面的站位) +``` +/* +Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) . For each element Ai in the array, count the number of element before this element Ai is smaller than it and return count number array. + +Example +For array [1,2,7,8,5], return [0,1,2,3,2] + +Note +We suggest you finish problem Segment Tree Build, Segment Tree Query II and Count of Smaller Number before itself I first. + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thoughts: + Just like Count of Smaller Number (in all given array A): + Create segment tree on index (0 ~ 10000) + Modify it to store count of equal or smaller numbers comparing to itself. + However, do query on every A[i] before calling 'modify'!!!!This is the trick. + Every time, before adding a new count information into the tree, do a query and return result. This way, it's always checking numbers before itself. +*/ +public class Solution { + + public class SegmentTreeNode { + public int start,end; + public int count; + public SegmentTreeNode left, right; + public SegmentTreeNode(int start, int end) { + this.start = start; + this.end = end; + this.count = 0; + this.left = null; + this.right = null; + } + } + + /* Build a empty segment tree based on index*/ + public SegmentTreeNode build(int start, int end) { + if (start > end) { + return null; + } + if (start == end) { + return new SegmentTreeNode(start, end); + } + SegmentTreeNode root = new SegmentTreeNode(start, end); + int mid = start + (end - start) / 2; + root.left = build(start, mid); + root.right = build(mid + 1, end); + return root; + } + + /* Update the tree with 'count': from bottom to this specific tree node, how many integers do we have.*/ + public void modify(SegmentTreeNode root, int index, int count){ + if (root.start == index && root.end == index) { + root.count += count; + return; + } + int mid = root.start + (root.end - root.start)/2; + if (root.start <= index && index <= mid) { + modify(root.left, index, count); + } + if (mid < index && index <= root.end) { + modify(root.right, index, count); + } + root.count = root.left.count + root.right.count; + } + + /* Look for that number based on start&&end*/ + public int query(SegmentTreeNode root, int start, int end) { + if (root.start == start && root.end == end) { + return root.count; + } + int sum = 0; + int mid = root.start + (root.end - root.start)/2; + if (end <= mid) { + sum += query(root.left, start, end); + } else if (start > mid) { + sum += query(root.right, start, end); + } else if (start <= mid && mid < end) { + sum += query(root.left, start, mid); + sum += query(root.right, mid + 1, end); + } + return sum; + } + + + /** + * @param A: An integer array + * @return: Count the number of element before this element 'ai' is + * smaller than it and return count number array + */ + public ArrayList countOfSmallerNumberII(int[] A) { + ArrayList rst = new ArrayList(); + + SegmentTreeNode root = build(0, 10000); + + for (int i = 0; i < A.length; i++) { + int count = 0; + if (A[i] > 0) { + count = query(root, 0, A[i] - 1); + } + rst.add(count); + modify(root, A[i], 1); + } + return rst; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Count of Smaller Number.java b/Others/old records/LintCode-Backup/Count of Smaller Number.java new file mode 100644 index 0000000..c8b4083 --- /dev/null +++ b/Others/old records/LintCode-Backup/Count of Smaller Number.java @@ -0,0 +1,216 @@ +和平时的segment tree问题不同。 +这个给了实际的value,而还是造一个based on index的segment tree才行。 +Thought1是失败的,因为虽然省了空间,但是search time还是O(n). +Thought2才是真正的segment tree (based on index interval). + +重要trick: +在query前,给进去的start和end是: 0 ~ value-1. +value-1就是说,找比自己所在range小1的range(那么自然而然地就不包括自己了),这样就找到了smaller number. +这个trick还挺刁钻的。 +``` +/* +Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) and an query list. For each query, give you an integer, return the number of element in the array that are smaller than the given integer. + + +Example +For array [1,2,7,8,5], and queries [1,8,5], return [0,4,2] + +Note +We suggest you finish problem Segment Tree Build and Segment Tree Query II first. + +Challenge +Could you use three ways to do it. + +Just loop +Sort and binary search +Build Segment Tree and Search. +Tags Expand +Binary Search LintCode Copyright Segment Tree + +*/ +/* + Thought2: http://www.jiuzhang.com/solutions/count-of-smaller-number/ + Build a tree based on index 0 ~ 10000. Then use modify to update the tree with proper 'count' value + Use query method to search for final results. + Each A[i] will be stored at index value of A[i]. + Count: how many numbers do we have from bottom till this level, including the A[i] itself. + For example, at the lowest A[i] spot, SegmentTreeNode(i,i), the count == 1. + + Note:Again, be careful on calculating the mid. It's usually based on root.start and root.end, instead of the target start,end interval. +*/ + +public class Solution { + + public class SegmentTreeNode { + public int start,end; + public int count; + public SegmentTreeNode left, right; + public SegmentTreeNode(int start, int end) { + this.start = start; + this.end = end; + this.count = 0; + this.left = null; + this.right = null; + } + } + + /* Build a empty segment tree based on index*/ + public SegmentTreeNode build(int start, int end) { + if (start > end) { + return null; + } + if (start == end) { + return new SegmentTreeNode(start, end); + } + SegmentTreeNode root = new SegmentTreeNode(start, end); + int mid = start + (end - start) / 2; + root.left = build(start, mid); + root.right = build(mid + 1, end); + return root; + } + + /* Update the tree with 'count': from bottom to this specific tree node, how many integers do we have.*/ + public void modify(SegmentTreeNode root, int index, int count){ + if (root.start == index && root.end == index) { + root.count += count; + return; + } + int mid = root.start + (root.end - root.start)/2; + if (index <= mid) { + modify(root.left, index, count); + } + if (index > mid) { + modify(root.right, index, count); + } + root.count = root.left.count + root.right.count; + } + + /* Look for that number based on start&&end*/ + public int query(SegmentTreeNode root, int start, int end) { + if (root.start == start && root.end == end) { + return root.count; + } + int sum = 0; + int mid = root.start + (root.end - root.start)/2; + if (end <= mid) { + sum += query(root.left, start, end); + } else if (start > mid) { + sum += query(root.right, start, end); + } else if (start <= mid && mid < end) { + sum += query(root.left, start, mid); + sum += query(root.right, mid + 1, end); + } + return sum; + } + + + /** + * @param A: An integer array + * @return: The number of element in the array that + * are smaller that the given integer + */ + public ArrayList countOfSmallerNumber(int[] A, int[] queries) { + ArrayList rst = new ArrayList(); + + SegmentTreeNode root = build(0, 10000); + for (int value : A) { + modify(root, value, 1); + } + for (int value : queries) { + int count = 0; + if (value > 0) { + count = query(root, 0, value - 1); + } + rst.add(count); + } + return rst; + } +} + + + + + + +/* + Time limit exceeded... + Because: If we build the tree based on given index 0~n, and build 'query' method based on its max values. It will work for small scale, but when it gets larger, we could be doing O(n)*m all the time. Everytime we search root.left and root.right, which is not binary search style : ) + + Thoughts: + Build SegmentTree, store max + 1st attempt: time exceeds. Because the 'query part' is actually not segment tree search. Doing search based on max value can find answer, but it's O(n) search. + Note: + This segment tree problem gives queries of actaul value, rather than a range(start,end) that we can directly use in segment tree. So we need some sort of conversion, that still provide (start,end) to search +*/ + +public class Solution { + public class SegmentTreeNode { + int start, end, max; + SegmentTreeNode left,right; + public SegmentTreeNode(int start, int end, int max){ + this.start = start; + this.end = end; + this.max = max; + this.left = null; + this.right = null; + } + } + + public SegmentTreeNode build(int[] A, int start, int end){ + if (A == null || A.length == 0) { + return null; + } + if (start == end) { + return new SegmentTreeNode(start, end, A[start]); + } + + int mid = (start + end)/2; + SegmentTreeNode left = build(A, start, mid); + SegmentTreeNode right = build(A, mid + 1, end); + SegmentTreeNode node = new SegmentTreeNode(start, end, Math.max(left.max, right.max)); + node.left = left; + node.right = right; + + return node; + } + + public int query(SegmentTreeNode root, int val) { + if (root == null) { + return 0; + } + if (root.start == root.end && root.max >= val) {//leaf, stll >= val + return 0; + } + if (root.max < val) { + return root.end - root.start + 1; + } + //root.max > val, but unknown if root.children could < val + return query(root.left, val) + query(root.right, val); + } + + + /** + * @param A: An integer array + * @return: The number of element in the array that + * are smaller that the given integer + */ + public ArrayList countOfSmallerNumber(int[] A, int[] queries) { + ArrayList rst = new ArrayList(); + if (queries == null || queries.length == 0) { + return rst; + } + + SegmentTreeNode root = build(A, 0, A.length - 1); + for (int num : queries) { + int count = 0; + if (root != null) { + count = query(root, num); + } + rst.add(count); + } + return rst; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Data Stream Median.java b/Others/old records/LintCode-Backup/Data Stream Median.java new file mode 100644 index 0000000..398f50d --- /dev/null +++ b/Others/old records/LintCode-Backup/Data Stream Median.java @@ -0,0 +1,62 @@ +/* +Numbers keep coming, return the median of numbers at every time a new number added. + +Have you met this question in a real interview? Yes +Example +For numbers coming list: [1, 2, 3, 4, 5], return [1, 1, 2, 2, 3]. + +For numbers coming list: [4, 5, 1, 3, 2, 6, 0], return [4, 4, 4, 3, 3, 3, 3]. + +For numbers coming list: [2, 20, 100], return [2, 2, 20]. + +Challenge +Total run time in O(nlogn). + +Clarification +What's the definition of Median? - Median is the number that in the middle of a sorted array. If there are n numbers in a sorted array A, the median is A[(n - 1) / 2]. For example, if A=[1,2,3], median is 2. If A=[1,19], median is 1. + +Tags Expand +LintCode Copyright Heap Priority Queue +*/ + + + +public class Solution { + /** + * @param nums: A list of integers. + * @return: the median of numbers + */ + public int[] medianII(int[] nums) { + int[] rst = new int[nums.length]; + if (nums == null || nums.length == 0) { + return rst; + } + + PriorityQueue minHeap = new PriorityQueue(); + PriorityQueue maxHeap = new PriorityQueue(10, new Comparator() { + public int compare(Integer x, Integer y) { + return y - x; + } + }); + + rst[0] = nums[0]; + maxHeap.offer(rst[0]); + + for (int i = 1; i < rst.length; i++){ + int preMedian = maxHeap.peek(); + if (nums[i] > preMedian) { + minHeap.offer(nums[i]); + } else { + maxHeap.offer(nums[i]); + } + + if (maxHeap.size() > minHeap.size() + 1) { + minHeap.offer(maxHeap.poll()); + } else if (maxHeap.size() < minHeap.size()) { + maxHeap.offer(minHeap.poll()); + } + rst[i] = maxHeap.peek(); + } + return rst; + } +} diff --git a/Others/old records/LintCode-Backup/Delete Digits.java b/Others/old records/LintCode-Backup/Delete Digits.java new file mode 100644 index 0000000..a9eaa58 --- /dev/null +++ b/Others/old records/LintCode-Backup/Delete Digits.java @@ -0,0 +1,114 @@ +/* +Given string A representative a positive integer which has N digits, remove any k digits of the number, the remaining digits are arranged according to the original order to become a new positive integer. + +Find the smallest integer after remove k digits. + +N <= 240 and k <= N, + +Example +Given an integer A = "178542", k = 4 + +return a string "12" + +Tags Expand +Greedy LintCode Copyright + +Attempt2,Thoughts: +loop k times: each interation, find one digit to remove +Rules: want to remove whatever digit at A[i] that's A[i] > A[i+1]. +Reason: Higher position (left side of the string) is always stronger/high number, and remove the strong/high digit will always be right option. +Well... thinking straight (attempt2) seems much easier to understand and to code up than my attempt1 + +Note: +remember to remove the prefixing 0's +*/ + +public class Solution { + /** + *@param A: A positive integer which has N digits, A is a string. + *@param k: Remove k digits. + *@return: A string + */ + public String DeleteDigits(String A, int k) { + if (A == null || A.length() == 0 || k == 0) { + return A; + } + for (int i = 0; i < k; i++) { + for (int j = 0; j < A.length(); j++) { + if (j == A.length() - 1) { + A = A.substring(0, j); + break; + } else if (A.charAt(j) > A.charAt(j + 1)) { + A = A.substring(0, j) + A.substring(j + 1); + break; + } + } + } + //remote prefixing-0's + int i = 0; + while(i < A.length() && A.charAt(i) == '0') { + i++; + } + return A.substring(i); + } +} + + + + +/* +Attempt1: Lintcode 83% correct, but Does not work for : [9876141516171818818181890001988181700198181778786761256512651653145345143, 55] +my output: 1111111134143 +expect: 1111111345143 + +Not sure where went wrong. + +Thoughts: +This seems to be: Pick (N - k) digits and make a smallest number, without changing the order of digits. +Create an array with length == (N - k): digits +Starting from i = 0, digits[0] = A.charAt[0] - '0' +if A[i] < digits[i] , replace digits[i] with A[i] + Note: here loop through (N - k) and see if the A[i] can be put anywhere + +Note: handle prefix '0' in string +*/ +public class Solution { + public static String DeleteDigits(String A, int k) { + if (A == null || A.length() == 0 || k < 0) { + return A; + } + int n = A.length() - k; + //System.out.println(A.length() + " " + n); + int[] digits = new int[n]; + for (int j = 0; j < n; j++) { + digits[j] = -1; + } + int[] backup = Arrays.copyOf(digits, digits.length); + for (int i = 0; i < A.length(); i++) { + int digit = (int)(A.charAt(i) - '0'); + + for (int j = 0; j < n; j++) { + if ((digit < digits[j] || digits[j] < 0) && (A.length() - i) >= (n - j)) { + //System.out.println(j + " " + digit + " | " + (A.length() - i) + " " + (n - j)); + if (j == 0) { + digits = Arrays.copyOf(backup, backup.length); + } + digits[j] = digit; + break; + } + } + } + //System.out.println(Arrays.toString(digits)); + String rst = ""; + for (int j = 0; j < n; j++) { + if (rst.length() == 0 && digits[j] == 0) { + continue; + } else { + rst += digits[j]; + } + } + + return rst; + } + +} diff --git a/Others/old records/LintCode-Backup/Delete Node in the Middle of Singly Linked List.java b/Others/old records/LintCode-Backup/Delete Node in the Middle of Singly Linked List.java new file mode 100644 index 0000000..355deb8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Delete Node in the Middle of Singly Linked List.java @@ -0,0 +1,40 @@ +/* +Implement an algorithm to delete a node in the middle of a singly linked list, given only access to that node. + +Example +Given 1->2->3->4, and node 3. return 1->2->4 + +Tags Expand +Cracking The Coding Interview Linked List + +Thoughts: +1. Only have this node, make it look like its next +2. remove next + +*/ + + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param node: the node in the list should be deleted + * @return: nothing + */ + public void deleteNode(ListNode node) { + if (node == null) { + return; + } + node.val = node.next.val; + node.next = node.next.next; + } +} diff --git a/Others/old records/LintCode-Backup/Distinct Subsequences.java b/Others/old records/LintCode-Backup/Distinct Subsequences.java new file mode 100644 index 0000000..35cf479 --- /dev/null +++ b/Others/old records/LintCode-Backup/Distinct Subsequences.java @@ -0,0 +1,110 @@ +/* +Given a string S and a string T, count the number of distinct subsequences of T in S. + +A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). + +Example +Given S = "rabbbit", T = "rabbit", return 3. + +Challenge +Do it in O(n2) time and O(n) memory. + +O(n2) memory is also acceptable if you do not know how to optimize memory. + +Tags Expand +String Dynamic Programming +*/ +/* +Attempt2: +Use DP. Okay, first I had no idea how to start, but here is a reference: http://blog.csdn.net/abcbc/article/details/8978146 +First of all, Map out the number of existance of T in S in a 2D map: + 0 1 2 3 4 5 6 7 + --------------- + r a b b b i t +0| 1 1 1 1 1 1 1 1 +1| r 0 1 1 1 1 1 1 1 +2| a 0 0 1 1 1 1 1 1 +3| b 0 0 0 1 2 3 3 3 +4| b 0 0 0 0 1 3 3 3 +5| i 0 0 0 0 0 0 3 3 +6| t 0 0 0 0 0 0 0 3 + +Use DP[T][S]. We realize: +1.DP[0][0] == 1; //Both null can be a match +2.DP[0][1 ~ S.length - 1] = 1;//First fow, when T=="", whatever S will have 1 subsequence: "" +3.DP[1 ~ T.length][0] = 0;// First column, when S=="", whatever T will not be subsequence of S == "" +4.When looking at each row and filling out the pixels, we realize when T exist in S[a~b], it will surely exist in S[a~b+1], taht is: + Step1: DP[i][j] is at least equal to DP[i][j - 1];//DP[i][j] is always based on DP[i][j-1], so DP[i][j] = DP[i][j+1] + something + Step2: So, what's that 'something' in step1? For example, look at T[3] == 'b' against S[0 ~ 3]: + S[0 ~ 3] has 1 'b' at S[3], and also, T[0~3] == S[0~3], that's a perfect match. SO DP[3][3] = 1 + S[0 ~ 4] has 2 'b' at S[3] and S[4]. Now imagine we pick either S[3] or S[4] to genreate T[0~3] out of S[0~4]: we have 2 possibilities.D[3][4] = 2 + Consider: D[i][j] means we picked S[j]; in our S[0 ~ 4] case, that means we picked S[4] but skipped S[3], though S[3] still counts towards another situation where we skipped S[4]. + After all, we will count whatever that we skipped into our current DP[i][j], that is DP[i][j] += T[i - 1] == S[j - 1] ? DP[i - 1][j - 1] : 0; + Conclusion: while we for-looping through each row, if we find out S[j] and S[j - 1] both equals to T[i - 1], we want to make sure we count D[i - 1][j -1]'s previous records in! + +Note: +In double for loop, set i,j <= xxxx.length(), since we've increased the 2D array by 1 block on row and col. +*/ + + +public class Solution { + /** + * @param S, T: Two string. + * @return: Count the number of distinct subsequences + */ + public int numDistinct(String S, String T) { + int[][] DP = new int[T.length() + 1][S.length() + 1]; + DP[0][0] = 1; + for(int i = 1; i < S.length(); i++) { + DP[0][i] = 1; + } + for (int i = 1; i < T.length(); i++) { + DP[i][0] = 0; + } + for (int i = 1; i <= T.length(); i++) { + for (int j = 1; j <= S.length(); j++){ + DP[i][j] = DP[i][j - 1]; + if (T.charAt(i - 1) == S.charAt(j - 1)) { + DP[i][j] += DP[i - 1][j - 1]; + } + } + } + return DP[T.length()][S.length()]; + } +} + + +/* +Attemp1: +recursive on substring of S, accumulate total count +However, exceed time limit +*/ +public class Solution { + public int numDistinct(String S, String T) { + if (S.length() == 0) { + return T.length() == 0 ? 1 : 0; + } + if (T.length() == 0) { + return 1; + } + int count = 0; + for (int i = 0; i < S.length(); i++) { + if (S.charAt(i) == T.charAt(0)) { + count += numDistinct(S.substring(i + 1), T.substring(1)); + } + } + return count; + } +} + + + +/* +First Thought: +find the # of ways to get T from S, while having to follow the rules of 'subsequence' +How about: find what chars are missing in T based on S, then find the number of ways to insert the missing chars to make it back to S? +The missing chars: misChars = new ArrayList(); +However, time cost on this: +For example I have n missing chars from S.length == m. so I have (m + 1) places where i can insert the n chars. Then it's a mCn problem. This goes up to m!, too much. Not applicapable. + +*/ \ No newline at end of file diff --git a/Java/Easy Reverse Linked List.java b/Others/old records/LintCode-Backup/Easy Reverse Linked List.java similarity index 100% rename from Java/Easy Reverse Linked List.java rename to Others/old records/LintCode-Backup/Easy Reverse Linked List.java diff --git a/Others/old records/LintCode-Backup/Edit Distance.java b/Others/old records/LintCode-Backup/Edit Distance.java new file mode 100644 index 0000000..916b78f --- /dev/null +++ b/Others/old records/LintCode-Backup/Edit Distance.java @@ -0,0 +1,58 @@ +/* +Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) + +You have the following 3 operations permitted on a word: + +Insert a character +Delete a character +Replace a character + +Example +Given word1 = "mart" and word2 = "karma", return 3. + +Tags Expand +String Dynamic Programming + +Thoughts: +Draw a 2D array, consider rows as word1 and cols as word2. +DP[i][j] means the steps (edit distance) to take to transfer word1[0 ~ i] to word2[0 ~ j] +And, we have 3 different calculations for the 3 methods: +1. Replace: DP[i][j] = word1[i-1] == word2[j-1] ? DP[i - 1][j - 1] : DP[i-1][j-1] + 1; +2. Insert: DP[i][j] = word1[i - 1][j] + 1; // missing 1 char in word1 +3. Delete: DP[i][j] = word1[i][j - 1] + 1; // extra char in word1 + +Note: just remember to start from i=1,j=1, because we are using DP[i-1][j-1], becareful with border case +*/ + + + +public class Solution { + /** + * @param word1 & word2: Two string. + * @return: The minimum number of steps. + */ + public int minDistance(String word1, String word2) { + if (word1 == null && word2 != null) { + return word2.length(); + } else if (word1 != null && word2 == null) { + return word1.length(); + } else if (word1 == null && word2 == null) { + return 0; + } + int[][] DP = new int[word1.length() + 1][word2.length() + 1]; + for (int i = 1; i <= word1.length(); i++) { + DP[i][0] = i; + } + for (int j = 1; j <= word2.length(); j++) { + DP[0][j] = j; + } + + for (int i = 1; i <= word1.length(); i++) { + for (int j = 1; j <= word2.length(); j++) { + DP[i][j] = Math.min(Math.min(DP[i - 1][j] + 1, DP[i][j - 1] + 1), word1.charAt(i - 1) == word2.charAt(j - 1) ? DP[i - 1][j - 1] : DP[i - 1][j - 1] + 1); + } + } + + return DP[word1.length()][word2.length()]; + } +} diff --git a/Others/old records/LintCode-Backup/Expression Evaluation.java b/Others/old records/LintCode-Backup/Expression Evaluation.java new file mode 100644 index 0000000..47df6b5 --- /dev/null +++ b/Others/old records/LintCode-Backup/Expression Evaluation.java @@ -0,0 +1,146 @@ +Build Expression Tree的另外一个变形。 +做的还是PostTraversal。先eval left, right, 然后eval符号。 + +注意Handle数字时,若左右Child全Null,那必定是我们weight最大的数字node了。 +若有个child是null,那就return另外一个node。 +还要注意: +过程中用个Long吧,最后结局在cast back to int. +``` +/* +Given an expression string array, return the final result of this expression + +Example +For the expression 2*6-(23+7)/(1+2), input is + +[ + "2", "*", "6", "-", "(", + "23", "+", "7", ")", "/", + (", "1", "+", "2", ")" +], +return 2 + +Note +The expression contains only integer, +, -, *, /, (, ). + +Tags Expand +LintCode Copyright Stack +*/ + +/* +Thoughts: +Build expression tree, then traverse it in post-traversal order. +Tricky point: Whenever that's a operator, do operation. return final result. +*/ + + +public class Solution { + /***** build expression tree******/ + class TreeNode { + int val; + String s; + TreeNode left; + TreeNode right; + public TreeNode(int val, String s) { + this.val = val; + this.s = s; + this.left = null; + this.right = null; + } + } + public TreeNode build(String[] expression) { + Stack stack = new Stack(); + int base = 0; + int val = 0; + + for (int i = 0; i < expression.length; i++) { + if (expression[i].equals("(")) { + base += 10; + continue; + } + if (expression[i].equals(")")) { + base -= 10; + continue; + } + val = getWeight(base, expression[i]); + + TreeNode node = new TreeNode(val, expression[i]); + while (!stack.isEmpty() && node.val <= stack.peek().val) { + node.left = stack.pop(); + } + if (!stack.isEmpty()) { + stack.peek().right = node; + } + stack.push(node); + + } + if (stack.isEmpty()) { + return null; + } + TreeNode rst = stack.pop(); + while (!stack.isEmpty()) { + rst = stack.pop(); + } + return rst; + } + //Calculate weight for characters + public int getWeight(int base, String s) { + if (s.equals("+") || s.equals("-")) { + return base + 1; + } + if (s.equals("*") || s.equals("/")) { + return base + 2; + } + return Integer.MAX_VALUE; + } + /***** build expression tree******/ + + /** + * @param expression: an array of strings; + * @return: an integer + */ + public int evaluateExpression(String[] expression) { + if (expression == null || expression.length == 0) { + return 0; + } + TreeNode root = build(expression); + if (root == null) { + return 0; + } + long rst = postTraversalEval(root); + return (int)rst; + } + + public long postTraversalEval(TreeNode node) { + if (node == null) { + return 0; + } + if (node.left == null && node.right == null) { + return Long.parseLong(node.s); + } + long left = postTraversalEval(node.left); + long right = postTraversalEval(node.right); + + if (node.left == null || node.right == null) { + return node.left == null ? right : left; + } + long rst = 0; + switch (node.s) { + case "*": + rst = left * right; + break; + case "/": + rst = left / right; + break; + case "+": + rst = left + right; + break; + case "-": + rst= left - right; + break; + } + return rst; + } +}; + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Expression Tree Build.java b/Others/old records/LintCode-Backup/Expression Tree Build.java new file mode 100644 index 0000000..795d3be --- /dev/null +++ b/Others/old records/LintCode-Backup/Expression Tree Build.java @@ -0,0 +1,69 @@ +和Max-tree一样,感谢http://blog.welkinlan.com/2015/06/29/max-tree-lintcode-java/ +这个题目是Min-tree, 头上最小,Logic 和max-tree如出一辙。 +注意虚拟的形态:treeNode,作用就是为了有个weight,好排序。 +要想想,Java这个strict mom,如果换做JavaScript, 直接在expressionTreeNode上面附加一个object就完了,哪还用什么另外一个TreeNode class. +O(n) +``` +public class Solution { + class TreeNode { + int val; + ExpressionTreeNode eNode; + public TreeNode(int val, String s) { + this.val = val; + eNode = new ExpressionTreeNode(s); + } + } + /** + * @param expression: A string array + * @return: The root of expression tree + */ + public ExpressionTreeNode build(String[] expression) { + if (expression == null || expression.length == 0) { + return null; + } + Stack stack = new Stack(); + int base = 0; + int val = 0; + + for (int i = 0; i < expression.length; i++) { + if (expression[i].equals("(")) { + base += 10; + continue; + } + if (expression[i].equals(")")) { + base -= 10; + continue; + } + val = getWeight(base, expression[i]); + TreeNode node = new TreeNode(val, expression[i]); + while (!stack.isEmpty() && node.val <= stack.peek().val) { + node.eNode.left = stack.pop().eNode; + } + if (!stack.isEmpty()) { + stack.peek().eNode.right = node.eNode; + } + stack.push(node); + } + if (stack.isEmpty()) { + return null; + } + TreeNode rst = stack.pop(); + while (!stack.isEmpty()) { + rst = stack.pop(); + } + return rst.eNode; + } + //Calculate weight for characters + public int getWeight(int base, String s) { + if (s.equals("+") || s.equals("-")) { + return base + 1; + } + if (s.equals("*") || s.equals("/")) { + return base + 2; + } + return Integer.MAX_VALUE; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Fast Power.java b/Others/old records/LintCode-Backup/Fast Power.java new file mode 100644 index 0000000..dca7b79 --- /dev/null +++ b/Others/old records/LintCode-Backup/Fast Power.java @@ -0,0 +1,45 @@ +/* +Calculate the a^n % b where a, b and n are all 32bit integers. + +Example +For 2^31 % 3 = 2 + +For 100^1000 % 1000 = 0 + +Challenge +O(logn) + +Tags Expand +Divide and Conquer + +Thoughts: +Learn online: +(a * b) % p = (a % p * b % p) % p +Than mean: a ^ n can be divided into a^(n/2) * a^(n/2), that can be used for recursion: divde and conqure. + +Note: when n is odd number, it cannot be evenly divided into n/2 and n/2. This case needs special treatment: n = n/2 + n/2 + 1; +*/ + +class Solution { + /* + * @param a, b, n: 32bit integers + * @return: An integer + */ + public int fastPower(int a, int b, int n) { + if (n == 0) { + return 1 % b; + } + if (n == 1) { + return a % b; + } + + long recurPow = fastPower(a, b, n / 2); + recurPow = (recurPow * recurPow) % b; + + if (n % 2 == 1) { + recurPow = recurPow * a % b; + } + + return (int)recurPow; + } +}; diff --git a/Others/old records/LintCode-Backup/Fibonacci.java b/Others/old records/LintCode-Backup/Fibonacci.java new file mode 100644 index 0000000..adf73eb --- /dev/null +++ b/Others/old records/LintCode-Backup/Fibonacci.java @@ -0,0 +1,49 @@ +/* +Find the Nth number in Fibonacci sequence. + +A Fibonacci sequence is defined as follow: + +The first two numbers are 0 and 1. +The i th number is the sum of i-1 th number and i-2 th number. +The first ten numbers in Fibonacci sequence is: + +0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ... + + +Example +Given 1, return 0 + +Given 2, return 1 + +Given 10, return 34 + +Note +The Nth fibonacci number won't exceed the max value of signed 32-bit integer in the test cases. + +Tags Expand +Enumeration Mathematics Non Recursion + +Thoughts: +1. If non-recursion, do for loop for that n +2. Note: this specfiic problem is not 0-based. it's 1-based. +3. return fib[n] +*/ + +class Solution { + /** + * @param n: an integer + * @return an integer f(n) + */ + public int fibonacci(int n) { + if (n <= 1) { + return 0; + } + int[] fib = new int[n + 1]; + fib[1] = 0; + fib[2] = 1; + for (int i = 3; i <= n; i++) { + fib[i] = fib[i - 1] + fib[i - 2]; + } + return fib[n]; + } +} diff --git a/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array II.java b/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array II.java new file mode 100644 index 0000000..83aa7c8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array II.java @@ -0,0 +1,41 @@ +/* +Medium Find Minimum in Rotated Sorted Array II My Submissions + +40% Accepted +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +Find the minimum element. + +The array may contain duplicates. + +Example +Given [4,4,5,6,7,0,1,2] return 0 + +Tags Expand +Binary Search Divide and Conqueri + +Thinking process: +It seems using binary search will leads to O(n), so just use a for loop with O(n) +*/ + +public class Solution { + /** + * @param num: a rotated sorted array + * @return: the minimum number in the array + */ + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return -1; + } + int min = Integer.MAX_VALUE; + for (int i = 0; i < num.length; i++) { + if (min > num[i]) { + min = num[i]; + } + } + return min; + } +} + diff --git a/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array.java b/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array.java new file mode 100644 index 0000000..a15ba64 --- /dev/null +++ b/Others/old records/LintCode-Backup/Find Minimum in Rotated Sorted Array.java @@ -0,0 +1,52 @@ +/* +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +Find the minimum element. + +You may assume no duplicate exists in the array. + +Example +Given [4,5,6,7,0,1,2] return 0 + +Tags Expand +Binary Search + +Thinking process: +Understand how to use binary in this problem: compare the mid point with end point. +In this problem, because the sorted line is cut at one point then rotate, so one of the line is absolutely greater than the other line. +Situation 1: +if mid < end : that means minimum is on the end point's line. Move end to left. end = mid. +Situation 2: +if mid > end: that means there must be a mountain-jump somewhere after mid and before end, which is the minimum point. Now move start to mid. +*/ + +public class Solution { + /** + * @param num: a rotated sorted array + * @return: the minimum number in the array + */ + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return -1; + } + int start = 0; + int end = num.length - 1; + int mid = 0; + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (num[mid] > num[end]) { + start = mid; + } else { + end = mid; + } + } + if (num[start] < num[end]) { + return num[start]; + } else { + return num[end]; + } + } +} + diff --git a/Others/old records/LintCode-Backup/Find Peak Element II.java b/Others/old records/LintCode-Backup/Find Peak Element II.java new file mode 100644 index 0000000..1629c93 --- /dev/null +++ b/Others/old records/LintCode-Backup/Find Peak Element II.java @@ -0,0 +1,52 @@ +/* +There is an integer matrix which has the following features: + +The numbers in adjacent positions are different. +The matrix has n rows and m columns. +For all i < m, A[0][i] < A[1][i] && A[n - 2][i] > A[n - 1][i]. +For all j < n, A[j][0] < A[j][1] && A[j][m - 2] > A[j][m - 1]. +We define a position P is a peek if: + +A[j][i] > A[j+1][i] && A[j][i] > A[j-1][i] && A[j][i] > A[j][i+1] && A[j][i] > A[j][i-1] +Find a peak element in this matrix. Return the index of the peak. + +Have you met this question in a real interview? Yes +Example +Given a matrix: + +[ + [1 ,2 ,3 ,6 ,5], + [16,41,23,22,6], + [15,17,24,21,7], + [14,18,19,20,10], + [13,14,11,10,9] +] +return index of 41 (which is [1,1]) or index of 24 (which is [2,2]) + +Note +The matrix may contains multiple peeks, find any of them. + +Challenge +Solve it in O(n+m) time. + +If you come up with an algorithm that you thought it is O(n log m) or O(m log n), can you prove it is actually O(n+m) or propose a similar but O(n+m) algorithm? + +Tags Expand +Binary Search LintCode Copyright Matrix +*/ + +/* + NOT DONE. Will try if have time +*/ + + +class Solution { + /** + * @param A: An integer matrix + * @return: The index of the peak + */ + public List findPeakII(int[][] A) { + // write your code here + } +} + diff --git a/Others/old records/LintCode-Backup/Find Peak Element.java b/Others/old records/LintCode-Backup/Find Peak Element.java new file mode 100644 index 0000000..0717014 --- /dev/null +++ b/Others/old records/LintCode-Backup/Find Peak Element.java @@ -0,0 +1,65 @@ +还是binary search. +一个特别的check condition, 和特别的move left, move right的case罢了。 +``` +/*There is an integer array which has the following features: + + * The numbers in adjacent positions are different. + + * A[0] < A[1] && A[A.length - 2] > A[A.length - 1]. + +We define a position P is a peek if A[P] > A[P-1] && A[P] > A[P+1]. + +Find a peak in this array. Return the index of the peak. + +Note +The array may contains multiple peeks, find any of them. + +Example +[1, 2, 1, 3, 4, 5, 7, 6] + +return index 1 (which is number 2) or 6 (which is number 7) + +Challenge +Time complexity O(logN) + +Tags Expand +Binary Search Array LintCode Copyright + +Thinking Process: +画图 +*/ + +class Solution { + /** + * @param A: An integers array. + * @return: return any of peek positions. + */ + public int findPeak(int[] A) { + int start = 1; + int end = A.length - 2; + int mid; + + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A[mid] > A[mid - 1] && A[mid] > A[mid + 1]) { + return mid; + //Tricky: only when start< mid < mid + 1, we can set start = mid; + //This is because we are cilmbing, so going up will finally find a peak + } else if (A[mid] > A[start] && A[mid] < A[mid + 1]) { + start = mid; + } else {// this case A[start] > A[mid], so we climb backwards, all make sense + end = mid; + } + }//while + + if (A[start] > A[start - 1] && A[start] > A[start + 1]) { + return start; + } else { + return end; + } + + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Find the Connected Component in the Undirected Graph.java b/Others/old records/LintCode-Backup/Find the Connected Component in the Undirected Graph.java new file mode 100644 index 0000000..694d25c --- /dev/null +++ b/Others/old records/LintCode-Backup/Find the Connected Component in the Undirected Graph.java @@ -0,0 +1,176 @@ +BFS遍历,把每个node的neighbor都加进来。 + +一定注意要把visit过的node Mark一下。因为curr node也会是别人的neighbor,会无限循环。 + +Component的定义:所有Component内的node必须被串联起来via path (反正这里是undirected, 只要链接上就好) + +这道题:其实component在input里面都已经给好了,所有能一口气visit到的,全部加进queue里面,他们就是一个component里面的了。 + +而我们这里不需要判断他们是不是Component。 +``` + /* +Find the number connected component in the undirected graph. +Each node in the graph contains a label and a list of its neighbors. +(a connected component (or just component) of an undirected graph is a subgraph in which + any two vertices are connected to each other by paths, +and which is connected to no additional vertices in the supergraph.) + +Example +Given graph: + +A------B C + \ | | + \ | | + \ | | + \ | | + D E +Return {A,B,D}, {C,E}. Since there are two connected component which is {A,B,D}, {C,E} + +Note +Tags Expand +Breadth First Search + + */ + +/** + * Definition for Undirected graph. + * class UndirectedGraphNode { + * int label; + * ArrayList neighbors; + * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } + * }; + */ + +/* +OPTS: 11.07.2015 +Try to use ae map to mark the nodes. Then do a BFS with queue +1. Mark each node in map. +2. BFS each node +3. Whenver one node is checked, mark it check +*/ + +public class Solution { + /** + * @param nodes a array of Undirected graph node + * @return a connected set of a Undirected graph + */ + public List> connectedSet(ArrayList nodes) { + List> rst = new ArrayList>(); + if (nodes == null || nodes.size() == 0) { + return rst; + } + + HashMap map = new HashMap(); + for (UndirectedGraphNode node : nodes) { + map.put(node.label, false); + } + + for (UndirectedGraphNode node : nodes) { + if (!map.get(node.label)) { + bfs(rst, node, map); + } + } + return rst; + } + + public void bfs(List> rst, UndirectedGraphNode node, HashMap map) { + Queue queue = new LinkedList(); + List list = new ArrayList(); + queue.add(node); + map.put(node.label, true); + UndirectedGraphNode temp; + while (!queue.isEmpty()) { + temp = queue.poll(); + list.add(temp.label); + for (UndirectedGraphNode neighbor : temp.neighbors) { + if (!map.get(neighbor.label)) { + queue.offer(neighbor); + map.put(neighbor.label, true); + } + } + } + Collections.sort(list); + rst.add(list); + } +} + + +/* +Thoughts: +How do we check for a connected graph (any two nodes are connected)? +Maybe check for each node: each node represents a lead to a subgraph, then check if this subgraph +is valid. + + +1. In real case, need to ask the intervier: can we assume the given nodes are valid, so that we only +need to check for success case? That means, we assume for example a linear list A-B-C does not exist. + +2. Then, we can use a 'set' to mark: we've checked this node. +3. Use a queue for BFS +4. Use a arraylist to save the results. +5. Key point: when the queue is empty(), that means one set of connected component is ready to go +6. Iterate through nodes, when it's not empty. + +More Notes:Have to do Collections.sort()....somehow it want me to sort the results? +Note2: Get rid of a node from nodes, whenever add it to component ... don't forget this. +Note3: Well, there is a chance that compoents are added, queue is cleaned, but nodes are empty as well.. +that means, need to catch the last case of 'remaining component' and add it to rst. + + +Review: +How list, ArrayList, Set, Queue work. +How to do: add, remove, sort + +Collections: Set, List, Queue + +List: ArrayList + +Set methods: add(), contains(?) +Queue methods: offer(E e), add(E e), poll() +ArrayList method: add(E e), isEmpty(), remove(object o) + +*/ + +public class Solution { + /** + * @param nodes a array of Undirected graph node + * @return a connected set of a Undirected graph + */ + public List> connectedSet(ArrayList nodes) { + List> rst = new ArrayList<>(); + if (nodes == null || nodes.size() == 0) { + return rst; + } + //Init: + Set checked = new HashSet(); + Queue queue = new LinkedList(); + ArrayList component = new ArrayList(); + + queue.offer(nodes.get(0)); + + while (!nodes.isEmpty()) { + if (queue.isEmpty()) { + Collections.sort(component); + rst.add(component); + queue.offer(nodes.get(0)); + component = new ArrayList(); + } else { + UndirectedGraphNode curr = queue.poll(); + if (!checked.contains(curr)) { + checked.add(curr); + component.add(curr.label); + nodes.remove(curr); + for (UndirectedGraphNode node : curr.neighbors) { + queue.add(node); + } + } + } + } + if (!component.isEmpty()) { + rst.add(component); + } + return rst; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Find the Weak Connected Component in the Directed Graph.java b/Others/old records/LintCode-Backup/Find the Weak Connected Component in the Directed Graph.java new file mode 100644 index 0000000..34f0384 --- /dev/null +++ b/Others/old records/LintCode-Backup/Find the Weak Connected Component in the Directed Graph.java @@ -0,0 +1,182 @@ +Identify这是个union-find问题还挺巧妙。 +看到了weak component的形式: 一个点指向所有,那么所有的点都有一个公共的parent,然后就是要找出这些点。 + +为何不能从一个点出发,比如A,直接print它所有的neighbors呢? + 不行,如果轮到了B点,那因为是directed,它也不知道A的情况,也不知道改如何继续加,或者下手。 + +所以,要把所有跟A有关系的点,或者接下去和A的neighbor有关系的点,都放进union-find里面,让这些点有Common parents. + +最后output的想法: +做一个 map 。 +之前我们不是给每个num都存好了parent了嘛。 +每个num都有个parent, 然后不同的parent就创造一个不同的list。 +最后,把Map里面所有的list拿出来就好了。 +``` +/* +Find the number Weak Connected Component in the directed graph. +Each node in the graph contains a label and a list of its neighbors. +(a connected set of a directed graph is a subgraph in which + any two vertices are connected by direct edge path.) + +Example +Given graph: + +A----->B C + \ | | + \ | | + \ | | + \ v v + ->D E <- F +Return {A,B,D}, {C,E,F}. Since there are two connected component which are {A,B,D} and {C,E,F} + +Note +Sort the element in the set in increasing order + +Tags Expand +Union Find +*/ + +/* +Thoughts: +When constructing the dataset before running the method, I guess DirectedGraphNode is contructed in a +way that one node shots to neighbors, but may not have neibors shooting back. +Then, there is a parent-child relationship, where we can use union-find + +[ idea is correct. Need to implement with proper union-find methods. + (Implementation here: http://www.jiuzhang.com/solutions/find-the-weak-connected-component-in-the-directed-graph/) + 1. for loop to construct: Map + 2. Create Map>. + 3. Find(node) return root, and add this node to the rootNode's list +] + +In NineChapter's definition: +I. UnionFind class takes HashSet, and makes maps of relatioinship. + 1. However, in UnionFind constructor, first step is just init + 2. Find method on a target element's root parent. If itself is root parent, then parent should = map.get(parent) + 3. Union method, if find(x) and find(y) are different, map them as child vs. parent. + +II. In main method: + 1. Create that HashSet for UnionFind. + 2. Use Find methods to tacke all parent vs neighbors + 3. Use union to map out the relationship between parent's root and each neighbor's root. + OKAY, so now the map should be done, saved within UnionFind. + +III. Generate results + For each element in HashSet, find their root, and add to that root list + +Note: +Be careful about the in generateRst method: looking for the root +*/ + +/** + * Definition for Directed graph. + * class DirectedGraphNode { + * int label; + * ArrayList neighbors; + * DirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } + * }; + */ +public class Solution { + class UnionFind { + HashMap map; + //Constructor: + UnionFind(HashSet set) { + map = new HashMap(); + for (int num : set) { + map.put(num, num); + } + } + //Find: + //Root parent should have itself as child in map + int find(int x) { + int parent = map.get(x); + while (parent != map.get(parent)) { + parent = map.get(parent); + } + return parent; + } + void union(int x, int y) { + int findX = find(x); + int findY = find(y); + if (findX != findY) { + map.put(findX, findY); + } + } + } + public List> generateRst (List> rst, UnionFind uf, HashSet set) { + + HashMap> listMap = new HashMap>(); + for (int num : set) { + int rootParent = uf.find(num);//uf.map.get(num); + if (!listMap.containsKey(rootParent)) { + listMap.put(rootParent, new ArrayList()); + } + //Add num into its correct set (meaning its root ancestor) + listMap.get(rootParent).add(num); + } + + for (List list: listMap.values()) { + Collections.sort(list); + rst.add(list); + } + return rst; + } + + public List> connectedSet2(ArrayList nodes) { + List> rst = new ArrayList>(); + if (nodes == null || nodes.size() == 0) { + return rst; + } + HashSet set = new HashSet(); + for (DirectedGraphNode node : nodes) { + set.add(node.label); + for (DirectedGraphNode neighbor : node.neighbors) { + set.add(neighbor.label); + } + } + UnionFind uf = new UnionFind(set); + + //find and union: construct the map structure + for (DirectedGraphNode node : nodes) { + for (DirectedGraphNode neighbor : node.neighbors) { + uf.union(node.label, neighbor.label); + } + } + return generateRst(rst, uf, set); + } + + +} + + + + + + + + + + + +/* + Can we do the following for find() ? Inspired by the union-find implemented with int[] + Sort of recurisvely trying to get the parent orign, instead of using a while loop? + I guess it's doable. +*/ +//Root parent should have itself as child in map +int find(int x) { + int parent = map.get(x); + if (parent != map.get(parent)) { + parent = map.get(parent); + map.put(x, parent); + } + return parent; +} + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/First Bad Version.java b/Others/old records/LintCode-Backup/First Bad Version.java new file mode 100644 index 0000000..3a13b36 --- /dev/null +++ b/Others/old records/LintCode-Backup/First Bad Version.java @@ -0,0 +1,113 @@ +根据isBadVersion的性质,判断还如何end=mid or start=mid. +isBadVersion 是有方向的嘛,一个点错了,后面全错。 +``` +/* +The code base version is an integer start from 1 to n. +One day, someone committed a bad version in the code case, +so it caused this version and the following versions are all failed in the unit tests. +Find the first bad version. + +You can call isBadVersion to help you determine which version is the first bad one. +The details interface can be found in the code's annotation part. + +Have you met this question in a real interview? Yes +Example +Given n = 5: + +isBadVersion(3) -> false +isBadVersion(5) -> true +isBadVersion(4) -> true +Here we are 100% sure that the 4th version is the first bad version. + +Note +Please read the annotation in code area to get the correct way to call isBadVersion in different language. +For example, Java is SVNRepo.isBadVersion(v) + +Challenge +You should call isBadVersion as few as possible. + +Tags Expand +Binary Search LintCode Copyright Facebook + +*/ + +/* + Recap: 12.07.2015. + Feels like to find the 1st occurance of the match. going left all the way. +*/ +/** + * public class SVNRepo { + * public static boolean isBadVersion(int k); + * } + * you can use SVNRepo.isBadVersion(k) to judge whether + * the kth code version is bad or not. +*/ +class Solution { + /** + * @param n: An integers. + * @return: An integer which is the first bad version. + */ + public int findFirstBadVersion(int n) { + if (n < 1) { + return 0; + } + int start = 1; + int end = n; + int mid; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (SVNRepo.isBadVersion(mid)) { + if (mid - 1 >= 1 && SVNRepo.isBadVersion(mid - 1)) { + end = mid; + } else { + return mid; + } + } else { + start = mid; + } + } + if (SVNRepo.isBadVersion(start)) { + return start; + } + return end; + } +} + + + + + + + +class Solution { + /** + * @param n: An integers. + * @return: An integer which is the first bad version. + */ + public int findFirstBadVersion(int n) { + int start = 1; + int end = n; + int mid; + + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (VersionControl.isBadVersion(mid)) { + end = mid; + } else { + start = mid; + } + }//end while + + if (VersionControl.isBadVersion(start)) { + return start; + } else if (VersionControl.isBadVersion(end)) { + return end; + } else { + return 0; + } + + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/First Missing Positive.java b/Others/old records/LintCode-Backup/First Missing Positive.java new file mode 100644 index 0000000..b2dc9c2 --- /dev/null +++ b/Others/old records/LintCode-Backup/First Missing Positive.java @@ -0,0 +1,59 @@ +/* +Given an unsorted integer array, find the first missing positive integer. + +Example +Given [1,2,0] return 3, and [3,4,-1,1] return 2. + +Challenge +Your algorithm should run in O(n) time and uses constant space. + +Tags Expand +Array + +Thoughts: +It means: after it's sorted, what's the first missing postive int counted from 1 ---> more + +1. Arrays.sort(); +2. count = first non-zero element in A. +3. count +1, and see if maches the current A[i]? + +NOTE: +Deal with negative and positive number separately +Watch out for redundant number: ask if the list has duplicated elements +*/ + + +public class Solution { + /** + * @param A: an array of integers + * @return: an integer + */ + public int firstMissingPositive(int[] A) { + if (A == null || A.length == 0) { + return 1; + } + Arrays.sort(A); + int count = -1; + for (int i = 0; i < A.length; i++) { + if (A[i] > 0) { + if (count < 0) {//process 1st positive element + count = A[i]; + if (count != 1) { + return 1; + } + } + else if (A[i] == A[i - 1]) {//watch out for duplicates + count--; + } + else if(A[i] != count) {//if not match, kick out + return count; + } + count++; + } + } + if (count < 0) {//if all negative, return 1 + return 1; + } + return count; + } +} \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Flatten Binary Tree to Linked List.java b/Others/old records/LintCode-Backup/Flatten Binary Tree to Linked List.java new file mode 100644 index 0000000..6ff61e1 --- /dev/null +++ b/Others/old records/LintCode-Backup/Flatten Binary Tree to Linked List.java @@ -0,0 +1,82 @@ +/* +Flatten Binary Tree to Linked List + +Flatten a binary tree to a fake "linked list" in pre-order traversal. + +Here we use the right pointer in TreeNode as the next pointer in ListNode. + +Example + 1 + \ + 1 2 + / \ \ + 2 5 => 3 + / \ \ \ + 3 4 6 4 + \ + 5 + \ + 6 +Note +Don't forget to mark the left child of each node to null. +Or you will get Time Limit Exceeded or Memory Limit Exceeded. + +Challenge +Do it in-place without any extra memory. + +Tags Expand +Binary Tree Depth First Search +*/ + + + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: a TreeNode, the root of the binary tree + * @return: nothing + */ + public TreeNode parentNode = null; + public void flatten(TreeNode root) { + if (root == null) { + return; + } + + if (parentNode != null) { + parentNode.left = null; + parentNode.right = root; + } + + parentNode = root; + TreeNode right = root.right; + flatten(root.left); + flatten(right); + } +} + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Gas Station.java b/Others/old records/LintCode-Backup/Gas Station.java new file mode 100644 index 0000000..90cc375 --- /dev/null +++ b/Others/old records/LintCode-Backup/Gas Station.java @@ -0,0 +1,56 @@ +/* +There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. + +You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations. + +Return the starting gas station's index if you can travel around the circuit once, otherwise return -1. + +Example +Given 4 gas stations with gas[i]=[1,1,3,1], and the cost[i]=[2,2,1,1]. The starting gas station's index is 2. + +Note +The solution is guaranteed to be unique. + +Challenge +O(n) time and O(1) extra space + +Tags Expand +Greedy + +Thoughts: +Loop through the gas station, and track the possible starting index. +Start from i = 0 ~ gas.length, and use a second pointer move to track how far we are travelling + calculate: remain += gas[i] - cost[i]. (remain + gas[i] - cost[i]: the remaining gas plus i's gas, can we make it to i+1 gas station?) + if remain < 0, fail. Note: if from i ~ j can't work, even it's possible that i can make it to i+1's station, but i+1 ~ j won't work still. + Thus, once i's station failed to get to x, set index = x + 1: we are moving on to next possible starting point. + +'total':simply indicates if we can make it a circle +*/ + +public class Solution { + /** + * @param gas: an array of integers + * @param cost: an array of integers + * @return: an integer + */ + public int canCompleteCircuit(int[] gas, int[] cost) { + if (gas == null || cost == null || gas.length == 0 || cost.length == 0) { + return -1; + } + int start = 0; + int remain = 0; + int total = 0; + for (int i = 0; i < gas.length; i++) { + remain += gas[i] - cost[i]; + if (remain < 0) { + remain = 0; + start = i + 1; + } + total += gas[i] - cost[i]; + } + if (total < 0) { + return -1; + } + return start; + } +} diff --git a/Others/old records/LintCode-Backup/Generate Parentheses.java b/Others/old records/LintCode-Backup/Generate Parentheses.java new file mode 100644 index 0000000..e14d824 --- /dev/null +++ b/Others/old records/LintCode-Backup/Generate Parentheses.java @@ -0,0 +1,134 @@ +递归。 +看thought.取或者不取(, ) +``` +/* +Generate Parentheses + +Given n pairs of parentheses, +write a function to generate all combinations of well-formed parentheses. + +Example +Given n = 3, a solution set is: + +"((()))", "(()())", "(())()", "()(())", "()()()" + +Tags Expand +String Backtracking Recursion Zenefits Google + +*/ + +/* + Thoughts: + //http://fisherlei.blogspot.com/2012/12/leetcode-generate-parentheses.html + Either put ( or ) + can only put ( when # of ( < n + can only put ) when # of ) < # of ( + If # of single '(' > 0, then we can put ')' + If n > 0, we can split: 1. close it with ')'; or 2. add '(' + when n-- becomese = 0 and #p = 0, rst.add + +*/ +public class Solution { + /** + * @param n n pairs + * @return All combinations of well-formed parentheses + */ + ArrayList rst = new ArrayList(); + public ArrayList generateParenthesis(int n) { + if (n <= 0) { + return rst; + } + ArrayList list = new ArrayList(); + helper(list, 0, 0, n); + return rst; + } + + public void helper(ArrayList list, int left, int right, int n) { + if (left == n && right == n) { + StringBuffer sb = new StringBuffer(); + for (String s : list) { + sb.append(s); + } + rst.add(sb.toString()); + return; + } + if (left < n) { + list.add("("); + helper(list, left + 1, right, n); + list.remove(list.size() - 1); + } + if (right < left) { + list.add(")"); + helper(list, left, right + 1, n); + list.remove(list.size() - 1); + } + } +} + + +/* + // + 1st attempt, timeout. + Thoughts: + n = 0, null + n = 1, trivial: () + Do i-- from n. For each i >= 2 + it can choose: close a paren + open another paren + front = ( + end = ) + helper(front, end, int n) + if (n == 1) { + front + "()" + end + rst.add // check duplicate + } + +*/ +public class Solution { + /** + * @param n n pairs + * @return All combinations of well-formed parentheses + */ + public ArrayList rst = new ArrayList(); + public ArrayList generateParenthesis(int n) { + if (n <= 0) { + return rst; + } else if (n == 1){ + rst.add("()"); + return rst; + } + helper("", "", n); + Collections.sort(rst); + return rst; + } + //3 + public void helper(String front, String end, int n) { + if (n == 1) { + String rt = front + "()" + end; + if (!rst.contains(rt)){ + rst.add(rt); + } + return; + } + n--; + + helper(front + "(", ")" + end, n); + helper(front + "()", end, n); + helper(front, "()" + end, n); + helper(front + end + "(", ")", n); + helper(front + end, "()", n); + helper(front + end + "()", "", n); + helper("(", ")" + front + end, n); + helper("()", front + end, n); + helper("","()" + front + end, n); + helper("(",front+end+")",n); + helper("(" + front+end,")",n); + helper("(" + front, end + ")",n); + helper("("+front+end+")", "", n); + helper("", "("+front+end+")", n); + + } + +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Graph Valid Tree.java b/Others/old records/LintCode-Backup/Graph Valid Tree.java new file mode 100644 index 0000000..18288cc --- /dev/null +++ b/Others/old records/LintCode-Backup/Graph Valid Tree.java @@ -0,0 +1,183 @@ +复习Union-Find的另外一个种形式。 +题目类型:查找2个元素是不是在一个set里面。如果不在,false. 如果在,那就合并成一个set,共享parent. +存储的关键都是:元素相对的index上存着他的root parent. + +另一个union-find, 用hashmap的:http://www.lintcode.com/en/problem/find-the-weak-connected-component-in-the-directed-graph/ +``` +/* +Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), +write a function to check whether these edges make up a valid tree. + +Example +Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true. + +Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false. + +Note +You can assume that no duplicate edges will appear in edges. +Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + +Tags Expand +Depth First Search Breadth First Search Union Find Facebook Zenefits Google + +*/ + +/* + Thoughts: do union-find. //http://www.jiuzhang.com/solutions/graph-valid-tree/ + How to check if we have disconnected pair? Think about it: + A valid tree has n-1 edges. If we have 1 disconnected pair, that means, + we lost 1 edge, like n-2 edgets now. + OR, keep thinking: if we have a cycle, which is a extra edge, that becomes n edgets. + Therefore, a first check (assume if with n-1 edgets is valid), just check if edges.lenght == n -1. + + Then, natually we can think of : what if missing a couple edges and have a couple cycles, + which makes edges.length == n - 1? + So if in this complex case, there must be >=1 cycles. Now just explicitly check for cycle. + How to use unin-find to check no cycle: +*** if a pair of node has same parent. If they do, that makes an triangle. False. + + What does Union-Find do? + Union-Find is a data structure (this problem implemented as a array), that union 2 sets and + checks if 2 elements are in the same set. + In another problem, it can be implemented with HashMap as well. + +*/ + +public class Solution { + int[] parents; + public boolean validTree(int n, int[][] edges) { + if (n - 1 != edges.length) { + return false; + } + parents = new int[n]; + //Init + for (int i = 0; i < parents.length; i++) { + parents[i] = i; + } + //Use union-find to detect if pair has common parents, and merge then to 1 set + for (int i = 0; i < edges.length; i++){ + if (find(edges[i][0]) == find(edges[i][1])) { + return false; + } + union(edges[i][0], edges[i][1]); + } + + return true; + } + + /* + Not only find parent, also update the spot parents[node] with parent node, recursively. + + *** The fact is, at all levels, if any curr != its parent, it'll trigger the find() method, + Then it makes sure parent node will be assigned to this curr node index. + + Goal: Mark curr node: who is your ancestor parent; and that indicates if other nodes are + in the same union as curr. + */ + public int find(int node) { + if (parents[node] == node) {//If curr node == its parent, return curr node. + return node; + } + //If curr node != its parent, we will attempt to find its grandparents, and assign to curr node. + parents[node] = find(parents[node]); + return parents[node]; + } + /* + Either union x into y, or the other way + */ + public void union(int x, int y) { + int findX = parents[x]; + int findY = parents[y]; + if (findX != findY) { + parents[findX] = findY; + } + } +} + + + + + + + + + + + +/* + Attempt failed: + check:No cycle.Connected. + Sort the input based on edges[i][0]. + However, this is wrong; both 0 and 1 index of an edge can be used a root. +*/ + +//Just use priorityqueue +public class Solution { + /** + * @param n an integer + * @param edges a list of undirected edges + * @return true if it's a valid tree, or false + */ + class Pair { + int from, to; + public Pair(int f, int t) { + this.from = f; + this.to = t; + } + } + public boolean validTree(int n, int[][] edges) { + if (n == 1) { + return true; + } + if (edges == null || edges.length == 0 || edges[0].length == 0 || n <= 0) { + return false; + } + HashSet set = new HashSet(); + PriorityQueue queue = new PriorityQueue(2, new Comparator(){ + public int compare(Pair A, Pair B){ + return A.from - B.from; + } + }); + + //add into queue, format it like pair(small, large) + for (int i = 0; i < edges.length; i++) { + if (edges[i][0] < edges[i][1]) { + queue.offer(new Pair(edges[i][0], edges[i][1])); + } else { + queue.offer(new Pair(edges[i][1], edges[i][0])); + } + } + //check + set.add(queue.peek().from);//0 + while (!queue.isEmpty()) { + Pair p = queue.poll(); + //check node existance && cycle + if (!set.contains(p.from) || set.contains(p.to)) { + return false; + } + set.add(p.to); + } + return true; + } +} + + + + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Happy Number.java b/Others/old records/LintCode-Backup/Happy Number.java new file mode 100644 index 0000000..cd29bbb --- /dev/null +++ b/Others/old records/LintCode-Backup/Happy Number.java @@ -0,0 +1,51 @@ +/* +Write an algorithm to determine if a number is happy. + +A happy number is a number defined by the following process: +Starting with any positive integer, replace the number by the sum of the squares of its digits, +and repeat the process until the number equals 1 (where it will stay), +or it loops endlessly in a cycle which does not include 1. +Those numbers for which this process ends in 1 are happy numbers. + +Example +19 is a happy number + +1^2 + 9^2 = 82 +8^2 + 2^2 = 68 +6^2 + 8^2 = 100 +1^2 + 0^2 + 0^2 = 1 +Tags Expand +Hash Table Mathematics +*/ + +/* + Thoughts: + Try some examples then find out: if it's not happy number, the 'sum of square of its digits' will + repeatedly occur. Use hashset to track existance. +*/ +public class Solution { + public boolean isHappy(int n) { + if (n <= 0) { + return false; + } + long sum = n; + HashSet set = new HashSet(); + while (sum != 1) { + String s = String.valueOf(sum); + sum = 0; + for (char c : s.toCharArray()){ + sum += (c-'0')*(c-'0'); + } + if (set.contains(sum)) { + return false; + } else { + set.add(sum); + } + } + return true; + } +} + + + + diff --git a/Others/old records/LintCode-Backup/Hash Function.java b/Others/old records/LintCode-Backup/Hash Function.java new file mode 100644 index 0000000..ba32154 --- /dev/null +++ b/Others/old records/LintCode-Backup/Hash Function.java @@ -0,0 +1,56 @@ +/* +In data structure Hash, hash function is used to convert a string(or any other type) +into an integer smaller than hash size and bigger or equal to zero. The objective of +designing a hash function is to "hash" the key as unreasonable as possible. +A good hash function can avoid collision as less as possible. +A widely used hash function algorithm is using a magic number 33, +consider any string as a 33 based big integer like follow: + +hashcode("abcd") = (ascii(a) * 33^3 + ascii(b) * 33^2 + ascii(c) *33^1 + ascii(d)*33^0) % HASH_SIZE + + = (97* 333 + 98 * 332 + 99 * 33 +100) % HASH_SIZE + + = 3595978 % HASH_SIZE + +here HASH_SIZE is the capacity of the hash table +(you can assume a hash table is like an array with index 0 ~ HASH_SIZE-1). + +Given a string as a key and the size of hash table, return the hash value of this key. + + + +Example +For key="abcd" and size=100, return 78 + +Clarification +For this problem, you are not necessary to design your own hash algorithm +or consider any collision issue, you just need to implement the algorithm as described. + +Tags Expand +Hash Table + +Thinking process: +Use given hash function. +However, need to consider integer overflow. +A simple way: save it as a long during calculation. Then return a (int). +*/ + +class Solution { + /** + * @param key: A String you should hash + * @param HASH_SIZE: An integer + * @return an integer + */ + public int hashCode(char[] key, int HASH_SIZE) { + if (key.length == 0) { + return 0; + } + long hashRst = 0; + for (int i = 0; i < key.length ; i++) { + hashRst = hashRst * 33 + (int)(key[i]); + hashRst = hashRst % HASH_SIZE; + } + return (int)hashRst; + } +}; + diff --git a/Others/old records/LintCode-Backup/HashWithArray.java b/Others/old records/LintCode-Backup/HashWithArray.java new file mode 100644 index 0000000..5b03fa9 --- /dev/null +++ b/Others/old records/LintCode-Backup/HashWithArray.java @@ -0,0 +1,69 @@ +/* + Self Test: + Implement HashTable with just array and integer. + + Thoughts: + A simple approach is to % size of the array, if the key exist, move 1 slot over. + + A bug will be: when exceeds the size of array, there will be no avialable space, + and it'll run into error. + + Inspired here :http://www.algolist.net/Data_structures/Hash_table/Simple_example + 1. create a entry class. + 2. hash the key, and put Entry into that hased index. +*/ + +Class Entry{ + int key; + int value; + public Entry(int key, int value) { + this.key = key; + this.value = value; + } + + public getKey(){ + return this.key; + } + + public getValue() { + return this.value; + } +} + +Class HashMap { + int[] table; + int SIZE = 128; + public HashMap(){ + table = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + table[i] = null; + } + } + + public void put(int key, int value){ + int hash = key % SIZE; + while (table[hash] != null && table[hash].getKey() != key) { + hash = (hash + 1) % SIZE; + } + table[key] = new Entry(key, value); + } + + public int get(int key) { + int hash = key % SIZE; + while (table[hash] != null && table[hash].getKey() != key) { + hash = (hash + 1) % SIZE; + } + if (table[hash] == null) { + return -1; + } + return table[hash].getValue(); + } +} + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Heapify.java b/Others/old records/LintCode-Backup/Heapify.java new file mode 100644 index 0000000..f4f17fe --- /dev/null +++ b/Others/old records/LintCode-Backup/Heapify.java @@ -0,0 +1,112 @@ +Heapify里面的siftdown的部分: + 只能从for(i = n/2-1 ~ 0), 而不能从for(i = 0 ~ n/2 -1) + 这是不是因为siftdown每次只顺脚下的孩子,所以必须中间开花,向上跑的时候才能确保脚下是符合heap规则的 + +``` +/* +Given an integer array, heapify it into a min-heap array. + +For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i]. +Have you met this question in a real interview? Yes +Example +Given [3,2,1,4,5], return [1,2,3,4,5] or any legal heap array. + +Challenge +O(n) time complexity + +Clarification +What is heap? + +Heap is a data structure, which usually have three methods: push, pop and top. where "push" add a new element the heap, "pop" delete the minimum/maximum element in the heap, "top" return the minimum/maximum element. + +What is heapify? +Convert an unordered integer array into a heap array. If it is min-heap, for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. + +What if there is a lot of solutions? +Return any of them. +Tags Expand +LintCode Copyright Heap +*/ + + +/* +Thoughts: +Based on the knowledge of Hash Heap: http://www.jiuzhang.com/solutions/hash-heap/ +Try to implement part of the Heap basis, heapify. + +In this problem, re-organize the input array to fit heap basis + +1. Compare next value with head. +2. If smaller than head, do a siftdown + +siftdown: +always swap with the smaller child +As long as left.child.i < array length, continue while: + If no right child, or left.val < right.val, + son = left. + else + son = right +Check if curr.val < son.val + if so, break, we are good. + If not, swap(curr,son) +curr = son, and move on the next round of while + + +NOTE: +The for loop start from i = n/2 -1, which makes the right-most index = 2*(n/2-1) + 1 = n - 2 + 1 = n-1. +*/ + + +public class Solution { + /** + * @param A: Given an integer array + * @return: void + */ + public void heapify(int[] A) { + if (A == null || A.length == 0) { + return; + } + int son = 0; + int currId = 0; + int leftId = 0; + int rightId = 0; + int n = A.length; + for (int i = n/2 - 1; i >= 0; i--) { + currId = i; + while (currId * 2 + 1 < n) { + leftId = currId * 2 + 1; + rightId = currId * 2 + 2; + if (rightId >= n || A[leftId] <= A[rightId]) { + son = leftId; + } else { + son = rightId; + } + if (A[currId] <= A[son]) { + break; + } else { + int temp = A[currId]; + A[currId] = A[son]; + A[son] = temp; + } + currId = son; + }//end while + + }//end for + } +} + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/House Robber.java b/Others/old records/LintCode-Backup/House Robber.java new file mode 100644 index 0000000..e021fce --- /dev/null +++ b/Others/old records/LintCode-Backup/House Robber.java @@ -0,0 +1,104 @@ +最基本的dp。 +看前一个或前两个的情况,再总和考虑当下的。 +思考的适合搞清楚当下的和之前的情况的关系。 +滚动数组的优化,就是确定了是这类“只和前一两个位子“相关的Fn而推出的。 +``` +/* +You are a professional robber planning to rob houses along a street. +Each house has a certain amount of money stashed, +the only constraint stopping you from robbing each of them is that +adjacent houses have security system connected and it will automatically +contact the police if two adjacent houses were broken into on the same night. + +Given a list of non-negative integers representing the amount of money of each house, +determine the maximum amount of money you can rob tonight without alerting the police. + +Have you met this question in a real interview? Yes +Example +Given [3, 8, 4], return 8. + +Challenge +O(n) time and O(1) memory. + +Tags Expand +Dynamic Programming + +*/ +/* + Thoughts: + dp[i]: the best we can rob by i. + If I'm at house i, I'll either pick i or not pick i. + Pick i: dp[i-2] + A[i] + Not pick i: dp[i+1] + fn: + dp[i] = Math.max(dp[i-1], dp[i-2] + A[i]) + Init: + dp[0] = A[0] + dp[1] = Math.max(A[0], A[1]) + Return: + dp[n-1] +*/ + +//O(n) space +public class Solution { + /** + * @param A: An array of non-negative integers. + * return: The maximum amount of money you can rob tonight + */ + public long houseRobber(int[] A) { + if (A == null || A.length == 0) { + return 0; + } else if (A.length == 1) { + return A[0]; + } + int n = A.length; + long[] dp = new long[n]; + dp[0] = A[0]; + dp[1] = Math.max(A[0], A[1]); + + for (int i = 2; i < n; i++) { + dp[i] = Math.max(dp[i-1], dp[i-2] + A[i]); + } + + return dp[n - 1]; + } +} + + +//O(1) space, 滚动数组。 +public class Solution { + public long houseRobber(int[] A) { + if (A == null || A.length == 0) { + return 0; + } else if (A.length == 1) { + return A[0]; + } + int n = A.length; + long[] dp = new long[2]; + dp[0] = A[0]; + dp[1] = Math.max(A[0], A[1]); + + for (int i = 2; i < n; i++) { + dp[i%2] = Math.max(dp[(i-1)%2], dp[(i-2)%2] + A[i]); + } + + return dp[(n - 1)%2]; + } +} + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Identical Binary Tree.java b/Others/old records/LintCode-Backup/Identical Binary Tree.java new file mode 100644 index 0000000..6aadd44 --- /dev/null +++ b/Others/old records/LintCode-Backup/Identical Binary Tree.java @@ -0,0 +1,56 @@ +Divide, && all. +注意 null states +``` +/* +Check if two binary trees are identical. Identical means the two binary trees have the same structure and every identical position has the same value. + +Example + 1 1 + / \ / \ + 2 2 and 2 2 + / / +4 4 +are identical. + + 1 1 + / \ / \ + 2 3 and 2 3 + / \ +4 4 +are not identical. +*/ + +/* + Thoughts: + Do a divide and conquer traversal on left and right. + && all results. +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param a, b, the root of binary trees. + * @return true if they are identical, or false. + */ + public boolean isIdentical(TreeNode a, TreeNode b) { + if (a == null && b == null) { + return true; + } else if ( a == null || b == null) { + return false; + } else { + return a.val == b.val && isIdentical(a.left, b.left) && isIdentical(a.right, b.right); + } + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Implement Queue by Two Stacks.java b/Others/old records/LintCode-Backup/Implement Queue by Two Stacks.java new file mode 100644 index 0000000..2f36582 --- /dev/null +++ b/Others/old records/LintCode-Backup/Implement Queue by Two Stacks.java @@ -0,0 +1,57 @@ +/* +As the title described, you should only use two stacks to implement a queue's actions. + +The queue should support push(element), pop() and top() where pop is pop the first(a.k.a front) element in the queue. + +Both pop and top methods should return the value of first element. + +Example +For push(1), pop(), push(2), push(3), top(), pop(), you should return 1, 2 and 2 + +Challenge +implement it by two stacks, do not use any other data structure and push, pop and top should be O(1) by AVERAGE. + +Thoughts: +1. Push everything into stack2: whatever comes in last, will be on top. +2. Pop and Top: return stack1's top element. +3. Initially, when stack1 is empty, need to reverse all stack2 and put into stack: like pouring water from cup stack2 into cup stack1. + Or:when stack1 has been top() over, pour stack2 into stack1 again: the stack2's bottom becomes stack1's top, which is correct: returning the oldest element of queue (front of queue) + +Tags Expand +LintCode Copyright Stack Queue +*/ + + +public class Solution { + private Stack stack1; + private Stack stack2; + public void pourS2ToS1(){ + while (!stack2.empty()) { + stack1.push(stack2.peek()); + stack2.pop(); + } + } + public Solution() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public void push(int element) { + stack2.push(element); + } + + public int pop() { + if (stack1.empty()) { + pourS2ToS1(); + } + return stack1.pop(); + } + + public int top() { + if (stack1.empty()) { + pourS2ToS1(); + } + return stack1.peek(); + } +} + diff --git a/Others/old records/LintCode-Backup/Implement Stack by Two Queues.java b/Others/old records/LintCode-Backup/Implement Stack by Two Queues.java new file mode 100644 index 0000000..686b8c9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Implement Stack by Two Queues.java @@ -0,0 +1,80 @@ +两个Queue,交互倒水 +用一个Temp做swap + +做法1: +逻辑在top()/pop()里, 每次换水,查看末尾项. + +做法2: +逻辑在push里面: +1. x 放q2。 +2. q1全部offer/append到q2. +3. 用一个Temp做swap q1, q2. +q1的头,就一直是最后加进去的值. +``` +/* +Implement Stack by Two Queues + +Implement a stack by two queues. The queue is first in first out (FIFO). +That means you can not directly pop the last element in a queue. + +Have you met this question in a real interview? Yes +Example +push(1) +pop() +push(2) +isEmpty() // return false +top() // return 2 +pop() +isEmpty() // return true +Tags Expand +Stack Queue + +*/ + +/* + Thoughts: + 2 queue are like two cups. We are fliping water into/out between q1 and q2. + pop and top are fliping water. + Use p1 as the base. +*/ + +class Stack { + private Queue q1 = new LinkedList(); + private Queue q2 = new LinkedList(); + // Push a new item into the stack + public void push(int x) { + q1.offer(x); + } + + // Pop the top of the stack + public void pop() { + while (q1.size() > 1) { + q2.offer(q1.poll()); + } + q1.poll(); + swap(); + } + + // Return the top of the stack + public int top() { + while (q1.size() > 1) { + q2.offer(q1.poll()); + } + int rst = q1.poll(); + q2.offer(rst); + swap(); + return rst; + } + + public void swap(){ + Queue temp = q1; + q1 = q2; + q2 = temp; + } + + // Check the stack is empty or not. + public boolean isEmpty() { + return q1.isEmpty(); + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Implement Stack.java b/Others/old records/LintCode-Backup/Implement Stack.java new file mode 100644 index 0000000..7c4a3dd --- /dev/null +++ b/Others/old records/LintCode-Backup/Implement Stack.java @@ -0,0 +1,61 @@ +stack 后入先出. +Data Structure: ArrayList +return/remove ArrayList的末尾项。 + +``` +/* + Implement Stack + +Implement a stack. You can use any data structure inside a stack except stack itself to implement it. + + +Example +push(1) +pop() +push(2) +top() // return 2 +pop() +isEmpty() // return true +push(3) +isEmpty() // return false +Tags Expand +Array Stack +*/ + +/* +Thoughts: +use arraylist and a index tracker - leng +push: add to end +pop: remove end +top: get end. +isEmpty: return length +*/ + +class Stack { + private ArrayList list = new ArrayList(); + // Push a new item into the stack + public void push(int x) { + list.add(x); + } + + // Pop the top of the stack + public void pop() { + if (list.size() > 0) { + list.remove(list.size() - 1); + } + } + + // Return the top of the stack + public int top() { + if (list.size() > 0) { + return list.get(list.size() - 1); + } + return -1; + } + + // Check the stack is empty or not. + public boolean isEmpty() { + return list.size() == 0; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Implement Trie.java b/Others/old records/LintCode-Backup/Implement Trie.java new file mode 100644 index 0000000..eab4dd0 --- /dev/null +++ b/Others/old records/LintCode-Backup/Implement Trie.java @@ -0,0 +1,115 @@ +HashMap构建Trie。 +Trie用来insert word,找word, 找prefix +``` +/* +Implement a trie with insert, search, and startsWith methods. + +Have you met this question in a real interview? Yes +Example +Note +You may assume that all inputs are consist of lowercase letters a-z. + +Tags Expand +Trie Facebook Uber Google +*/ + +/** + * Your Trie object will be instantiated and called as such: + * Trie trie = new Trie(); + * trie.insert("lintcode"); + * trie.search("lint"); will return false + * trie.startsWith("lint"); will return true + */ + +/* + Thoughts: + - Trie is a like a dictionary that's populated based on given input. + - Each level indicates each index of the word, where in each level there are multiple separate nodes + (depending on how many words we have used to populate the trie ) + - At end of a string, mark it as end == true; + + - search: find end of word && end == true && + - startWith: find till end of prefix +*/ +class TrieNode { + HashMap children; + boolean isEnd; + // Initialize your data structure here. + public TrieNode() { + this.children = new HashMap(); + this.isEnd = false; + } +} + +public class Solution { + private TrieNode root; + + public Solution() { + root = new TrieNode(); + } + + // Inserts a word into the trie. + public void insert(String word) { + if (word == null || word.length() == 0) { + return; + } + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!node.children.containsKey(c)) { + node.children.put(c, new TrieNode()); + } + node = node.children.get(c); + if (i == word.length() - 1) { + node.isEnd = true; + } + } + } + + // Returns if the word is in the trie. + public boolean search(String word) { + if (word == null || word.length() == 0) { + return true; + } + + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + char c = word.charAt(i); + if (!node.children.containsKey(c)) { + return false; + } + node = node.children.get(c); + } + return node.isEnd; + } + + // Returns if there is any word in the trie + // that starts with the given prefix. + public boolean startsWith(String prefix) { + if (prefix == null || prefix.length() == 0) { + return true; + } + + TrieNode node = root; + for (int i = 0; i < prefix.length(); i++) { + char c = prefix.charAt(i); + if (!node.children.containsKey(c)) { + return false; + } + node = node.children.get(c); + } + return true; + } +} + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Insert Interval.java b/Others/old records/LintCode-Backup/Insert Interval.java new file mode 100644 index 0000000..8498a3e --- /dev/null +++ b/Others/old records/LintCode-Backup/Insert Interval.java @@ -0,0 +1,75 @@ +/* +Given a non-overlapping interval list which is sorted by start point. + +Insert a new interval into it, make sure the list is still in order and non-overlapping (merge intervals if necessary). + +Have you met this question in a real interview? Yes +Example +Insert [2, 5] into [[1,2], [5,9]], we get [[1,9]]. + +Insert [3, 4] into [[1,2], [5,9]], we get [[1,2], [3,4], [5,9]]. + +Tags Expand +Basic Implementation + +Thoughts: +1. Find right position to insert: find the last start position that's <= newInterval.start +2. After insertion, merge. +3. How to merge? Look at merge inerval question +*/ + + + +/** + * Definition of Interval: + * public classs Interval { + * int start, end; + * Interval(int start, int end) { + * this.start = start; + * this.end = end; + * } + */ +class Solution { + /** + * Insert newInterval into intervals. + * @param intervals: Sorted interval list. + * @param newInterval: A new interval. + * @return: A new sorted interval list. + */ + public ArrayList insert(ArrayList intervals, Interval newInterval) { + if (intervals == null || intervals.size() == 0 || newInterval == null) { + if (newInterval != null) { + intervals.add(newInterval); + } + return intervals; + } + //Insert + int start = newInterval.start; + int front = -1; + for (int i = 0; i < intervals.size(); i++) { + if (intervals.get(i).start <= start) { + front = i; + } + } + if (front == -1) { + intervals.add(0, newInterval); + } + intervals.add(front + 1, newInterval); + + //Merge + Interval pre = intervals.get(0); + Interval curr = null; + for (int i = 1; i < intervals.size(); i++) { + curr = intervals.get(i); + if (pre.end >= curr.start) { + pre.end = pre.end > curr.end ? pre.end : curr.end; + intervals.remove(i); + i--; + } else { + pre = curr; + } + } + + return intervals; + } +} \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Insert Node in a Binary Search Tree .java b/Others/old records/LintCode-Backup/Insert Node in a Binary Search Tree .java new file mode 100644 index 0000000..d44d293 --- /dev/null +++ b/Others/old records/LintCode-Backup/Insert Node in a Binary Search Tree .java @@ -0,0 +1,76 @@ +/* +43% Accepted +Given a binary search tree and a new tree node, insert the node into the tree. You should keep the tree still be a valid binary search tree. + +Example +Given binary search tree as follow: + + 2 + + / \ + +1 4 + + / + + 3 + +after Insert node 6, the tree should be: + + 2 + + / \ + +1 4 + + / \ + + 3 6 + +Challenge +Do it without recursion + +Tags Expand +Binary Search Tree LintCode Copyright + +Thinking process: +Binary Search Tree: +parent must < left node +parent must > right node +use a dummy node runNode to flow around on the binary search tree, compare with target node. +Find the leaf node and add into appropriate pos. +*/ + +public class Solution { + /** + * @param root: The root of the binary search tree. + * @param node: insert this node into the binary search tree + * @return: The root of the new binary search tree. + */ + public TreeNode insertNode(TreeNode root, TreeNode node) { + if (root == null) { + root = node; + return root; + } + TreeNode runNode = root; + TreeNode parentNode = null; + while (runNode != null) { + parentNode = runNode; + if (runNode.val > node.val) { + runNode = runNode.left; + } else { + runNode = runNode.right; + } + }//while + + if (parentNode != null) { + if (parentNode.val > node.val) { + parentNode.left = node; + } else { + parentNode.right = node; + } + } + return root; + } +} + diff --git a/Others/old records/LintCode-Backup/Insertion Sort List.java b/Others/old records/LintCode-Backup/Insertion Sort List.java new file mode 100644 index 0000000..b9d1b74 --- /dev/null +++ b/Others/old records/LintCode-Backup/Insertion Sort List.java @@ -0,0 +1,110 @@ +想明白原理就好做了: +基本上就是正常的想法:已经有个sorted list, insert一个element进去。怎么做? + while 里面每个元素都小于 curr, keep going + 一旦curr在某个点小了,加进去当下这个空隙。 +这个题目也就是:把list里面每个元素都拿出来,scan and insert一遍! + +``` +/* +Sort a linked list using insertion sort. + +Example +Given 1->3->2->0->null, return 0->1->2->3->null. + +Tags Expand +Sort Linked List +*/ + + +/* + Recap. 12.10.2015 + http://www.cnblogs.com/springfor/p/3862468.html + + Assumed we have a sorted list: now we pick each element and insert into that sorted list. + This is insertion. + + If we are constly picking from (o ~ n) of this list itself, it becomes Insertion sort. + + 1. make a sortedList, Now we need to have pre,curr,next for wapping, whenever we find the correct curr + 2. a pre node pointer [used to store the list each time to check where to insert curr], + 3. curr is the node being check very round + 4. next is simply used for wapping, not much other usage +*/ +public class Solution { + /** + * @param head: The first node of linked list. + * @return: The head of linked list. + */ + public ListNode insertionSortList(ListNode head) { + if (head == null || head.next == null) { + return head; + } + + ListNode sortedListHead = new ListNode(0);//dummy head + ListNode pre,curr,next; + curr = head; + + while (curr != null) {// insert every single curr into sorted list + next = curr.next; //prepare for insertion && swapping. + pre = sortedListHead;//the list to scan + while (pre.next != null && pre.next.val <= curr.val) { + //as long as pre and its front are sorted ascending, keep going + pre = pre.next; + } + //when pre.next == null , or curr is less than a node in pre.next, we want to insert curr before that pre.next node + curr.next = pre.next; + pre.next = curr; + + curr = next;//use the original next, instead of the new curr.next + }//end while + + return sortedListHead.next; + } +} + + + +/* +Thoughts: +Look at head pointer, which is the current element we focus on. +If it's greater than the next pointer value, we move on. Use a while loop to check the entire +list every time with a new head. +If the head.val is less/equal than the next.val, we stop the at this next pointer, then cut it, +insert head. +*/ +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @return: The head of linked list. + */ + public ListNode insertionSortList(ListNode head) { + if (head == null) { + return null; + } + ListNode dummy = new ListNode(0); + while (head != null) { + ListNode node = dummy; + while (node.next != null && node.next.val < head.val) { + node = node.next; + } + ListNode temp = head.next; + head.next = node.next; + node.next = head; + head = temp; + } + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Interleaving Positive and Negative Numbers.java b/Others/old records/LintCode-Backup/Interleaving Positive and Negative Numbers.java new file mode 100644 index 0000000..4463fb2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Interleaving Positive and Negative Numbers.java @@ -0,0 +1,63 @@ +不管遇到啥,先排个序。 +这里主要要特别考虑,正数多还是负数多的问题。 +count一下,然后举两个小栗子就看出来端倪了。 +然后Two Pointer +``` +/* +Given an array with positive and negative integers. Re-range it to interleaving with positive and negative integers. + +Example +Given [-1, -2, -3, 4, 5, 6], after re-range, it will be [-1, 5, -2, 4, -3, 6] or any other reasonable answer. + +Note +You are not necessary to keep the original order of positive integers or negative integers. + +Challenge +Do it in-place and without extra memory. + +Tags Expand +Two Pointers +*/ + +/* + Thoughts: + Sort, so it becomes [-1,-2,-3,-4,4,5,6,7] + Two pointer start,end. + Every round, start +=2, end -= 2; + Note: have to find out how many negative/positive integers first. +*/ + +class Solution { + /** + * @param A: An integer array. + * @return: void + */ + public void rerange(int[] A) { + if (A == null || A.length == 0) { + return; + } + Arrays.sort(A); + int count = 0; + for (int num : A){ + count += num >= 0 ? 1 : -1; + } + int start = 0; + int end = A.length - 1; + if (count < 0) { + start++; + } else if (count > 0){ + end--; + } + + while (start < end) { + if (A[start] < 0 && A[end] >= 0) { + int temp = A[start]; + A[start] = A[end]; + A[end] = temp; + } + start += 2; + end -= 2; + } + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Interleaving String.java b/Others/old records/LintCode-Backup/Interleaving String.java new file mode 100644 index 0000000..a1b4c87 --- /dev/null +++ b/Others/old records/LintCode-Backup/Interleaving String.java @@ -0,0 +1,101 @@ +/* +Given three strings: s1, s2, s3, determine whether s3 is formed by the interleaving of s1 and s2. + +Example +For s1 = "aabcc", s2 = "dbbca" + +When s3 = "aadbbcbcac", return true. +When s3 = "aadbbbaccc", return false. +Challenge +O(n2) time or better + +Tags Expand +Longest Common Subsequence Dynamic Programming + +Attempt2: DP[i][j]: boolean that if first S1(i) chars and first S2(j) chars can interleavign first S3(i + j) +Match one char by one char. We have 2 conditions: match s1 or s2 char, Let's do double-for-loop on s1 and s2 +1. match s1: s3.charAt(i + j -1) == s1.charAt(i - 1) && DP[i - 1][j]; // makes sure DP[i-1][j] also works before adding s1[i-1] onto the match list +2. match s2: s3.charAt(i + j -1) == s2.charAt(j - 1) && DP[i][j - 1]// similar as above + +Note: +Need to initiate the starting conditions with just s1, or just s2 +Note2: +DP ususally start i == 1, and always use (i - 1) in the loop... this is all because we are trying to get DP[i][j], which are 1 index more than length +*/ +public class Solution { + public boolean isInterleave(String s1, String s2, String s3) { + if (s3 == null || (s1 == null && s2 == null) || s1.length() + s2.length() != s3.length()) { + return false; + } + boolean[][] DP = new boolean[s1.length() + 1][s2.length() + 1]; + DP[0][0] = true; // empty s1 and s2 would be a working case + + //with just s1: + for (int i = 1; i <= s1.length(); i++) { + if (s3.charAt(i - 1) == s1.charAt(i - 1) && DP[i - 1][0]) { + DP[i][0] = true; + } + } + + //with just s2: + for (int j = 1; j <= s2.length(); j++) { + if (s3.charAt(j - 1) == s2.charAt(j - 1) && DP[0][j - 1]) { + DP[0][j] = true; + } + } + + for (int i = 1; i <= s1.length(); i++) { + for (int j = 1; j <= s2.length(); j++) { + if ((s3.charAt(i + j - 1) == s1.charAt(i - 1) && DP[i - 1][j]) + || (s3.charAt(i + j - 1) == s2.charAt(j - 1) && DP[i][j - 1])) { + DP[i][j] = true; + } + } + } + + return DP[s1.length()][s2.length()]; + } +} + + + + +/* + +Attempt1, Incorrect: tho, magically passed 91% of lintcode, by coincidence +This solution could goes on and on with s1, and failed at certain point when j == 0 does not fit in. +s1 = "sdfjas;dfjoisdu" +s2 = "dfnakd" +s3 = "sdfjas;dfjoisdf..." // Failed at that 'f' in s3 + +Thoughts: +DP[mxn]: loop through S1.length and S2.length, record DP[k] = true or false. +DP[k] = (S1(0~i) + S2(0 ~ j)) is leading S3: index of (xxx) == 0. + +*/ +public class Solution { + + public boolean isInterleave(String s1, String s2, String s3) { + if (s3 == null || (s1 == null && s2 == null) || s1.length() + s2.length() != s3.length()) { + return false; + } + + int i = 0; + int j = 0; + String base = ""; + for (int k = 0; k < s1.length()*s2.length() - 1; k++) { + if (i < s1.length() || j < s2.length()) { + if (i < s1.length() && s3.indexOf(base + s1.charAt(i)) == 0) { + base += s1.charAt(i); + i++; + } else if (j < s2.length() && s3.indexOf(base + s2.charAt(j)) == 0) { + base += s2.charAt(j); + j++; + } else { + return false; + } + } + } + return true; + } +} diff --git a/Others/old records/LintCode-Backup/Intersection of Two Linked Lists.java b/Others/old records/LintCode-Backup/Intersection of Two Linked Lists.java new file mode 100644 index 0000000..7363445 --- /dev/null +++ b/Others/old records/LintCode-Backup/Intersection of Two Linked Lists.java @@ -0,0 +1,95 @@ +E + +长短list,找重合点。 +长度不同的话,切掉长的list那个的extra length。 那么起点一样后,重合点就会同时到达。 + + +``` +/* +Write a program to find the node at which the intersection of two singly linked lists begins. + +Example +The following two linked lists: + +A: a1 → a2 + ↘ + c1 → c2 → c3 + ↗ +B: b1 → b2 → b3 +begin to intersect at node c1. + +Note +If the two linked lists have no intersection at all, return null. +The linked lists must retain their original structure after the function returns. +You may assume there are no cycles anywhere in the entire linked structure. +Challenge +Your code should preferably run in O(n) time and use only O(1) memory. + +Tags Expand +Linked List +*/ + +/* + Thoughts: + If a and b share some part, if cut off the extra header of b (seen in above example), they should start at same index and touch c1 at same time. + So traverse a, b, and calculate countA, countB => dif = countB - countA. + cut off the extra, then start iterating to find c1. + +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + +public class Solution { + /** + * @param headA: the first list + * @param headB: the second list + * @return: a ListNode + */ + public ListNode getIntersectionNode(ListNode headA, ListNode headB) { + if (headA == null || headB == null) { + return null; + } + int countA = 0; + int countB = 0; + int diff = 0; + ListNode node = headA; + while (node != null) { + countA++; + node = node.next; + } + node = headB; + while (node != null) { + countB++; + node = node.next; + } + diff = Math.abs(countA - countB); + node = (countA > countB) ? headA : headB; + while (diff != 0) { + diff--; + node = node.next; + } + ListNode nodeA = (countA > countB) ? node : headA; + ListNode nodeB = (countA > countB) ? headB : node; + while (nodeA != null && nodeB != null) { + if (nodeA == nodeB) { + return nodeA; + } + nodeA = nodeA.next; + nodeB = nodeB.next; + } + + return null; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Interval Minimum Number.java b/Others/old records/LintCode-Backup/Interval Minimum Number.java new file mode 100644 index 0000000..13b5047 --- /dev/null +++ b/Others/old records/LintCode-Backup/Interval Minimum Number.java @@ -0,0 +1,118 @@ +又一个Segment tree的例子。 +把min number存在区间里面。 + +类似的有存:max, sum, min, count + +如果考到的几率不高。那么这一系列题目就是练习写代码的能力,和举一反三的心态。 +``` +/* +Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. Each query has two integers [start, end]. For each query, calculate the minimum number between index start and end in the given array, return the result list. + +Example +For array [1,2,7,8,5], and queries [(1,2),(0,4),(2,4)], return [2,1,5] + +Note +We suggest you finish problem Segment Tree Build, Segment Tree Query and Segment Tree Modify first. + +Challenge +O(logN) time for each query + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thoughts: + Build a SegmentMinTree. + Do search using the interval +*/ + +/** + * Definition of Interval: + * public classs Interval { + * int start, end; + * Interval(int start, int end) { + * this.start = start; + * this.end = end; + * } + */ +public class Solution { + class SegmentMinTreeNode { + int start,end,min; + SegmentMinTreeNode left, right; + public SegmentMinTreeNode(int start, int end, int min) { + this.start = start; + this.end = end; + this.min = min; + this.left = null; + this.right = null; + } + } + + public SegmentMinTreeNode build(int start, int end, int[] A) { + if (start == end) { + return new SegmentMinTreeNode(start, end, A[start]); + } + int min = (start + end) / 2; + SegmentMinTreeNode left = build(start, min, A); + SegmentMinTreeNode right = build(min + 1, end, A); + SegmentMinTreeNode node = new SegmentMinTreeNode(start, end, Math.min(left.min, right.min)); + node.left = left; + node.right = right; + + return node; + } + + public int search(SegmentMinTreeNode root, int start, int end){ + if (root.start == start && root.end == end) { + return root.min; + } + + int mid = (root.start + root.end) / 2; + if (end <= mid) { + return search(root.left, start, end); + } + if (start > mid) { + return search(root.right, start, end); + } + + return Math.min(search(root.left, start, root.left.end), search(root.right, root.right.start, end)); + } + + + /** + *@param A, queries: Given an integer array and an query list + *@return: The result list + */ + public ArrayList intervalMinNumber(int[] A, ArrayList queries) { + ArrayList rst = new ArrayList(); + if (A == null || A.length == 0 || queries == null || queries.size() == 0) { + return rst; + } + SegmentMinTreeNode root = build(0, A.length - 1, A); + for (Interval range : queries) { + int min = search(root, range.start, range.end); + rst.add(min); + } + return rst; + } +} + + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Interval Sum II.java b/Others/old records/LintCode-Backup/Interval Sum II.java new file mode 100644 index 0000000..32e5a9d --- /dev/null +++ b/Others/old records/LintCode-Backup/Interval Sum II.java @@ -0,0 +1,123 @@ +这个题如果一上来就是做,拿的确烧脑,原因只有一个:太长了呀。就像Expression Tree一样。一旦知道了怎么做,就简单了,可如果生疏,也就难。 +这题是好几个SegmentTree的结合,但是没什么创新的。 +``` +/* +Given an integer array in the construct method, implement two methods query(start, end) and modify(index, value): + +For query(start, end), return the sum from index start to index end in the given array. +For modify(index, value), modify the number in the given index to value + +Example +Given array A = [1,2,7,8,5]. + +query(0, 2), return 10. +modify(0, 4), change A[0] from 1 to 4. +query(0, 1), return 6. +modify(2, 1), change A[2] from 7 to 1. +query(2, 4), return 14. +Note +We suggest you finish problem Segment Tree Build, Segment Tree Query and Segment Tree Modify first. + +Challenge +O(logN) time for query and modify. + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thought: + This is doing the SegmentSumTree all over again, and also the Segment Tree Modify method. + 1. Create SegmentSumTreeNode + 2. Build it by segment tree definition + 3. query: binary search and calcualte sum + 4. modify: binary search, and re-compare the max at each level. +*/ +public class Solution { + /* you may need to use some attributes here */ + class SegmentSumTreeNode { + int start,end; + long sum; + SegmentSumTreeNode left,right; + public SegmentSumTreeNode(int start, int end, long sum){ + this.start = start; + this.end = end; + this.sum = sum; + this.left = null; + this.right = null; + } + } + public SegmentSumTreeNode build(int start, int end, int[] A) { + if (start == end) { + return new SegmentSumTreeNode(start, end, A[start]); + } + int mid = (start + end)/2; + SegmentSumTreeNode left = build(start, mid, A); + SegmentSumTreeNode right = build(mid + 1, end, A); + + SegmentSumTreeNode node = new SegmentSumTreeNode(start, end, left.sum + right.sum); + node.left = left; + node.right = right; + return node; + } + + SegmentSumTreeNode root = null; + /** + * @param A: An integer array + */ + public Solution(int[] A) { + if (A == null || A.length == 0) { + return; + } + root = build(0, A.length - 1, A); + } + + /** + * @param start, end: Indices + * @return: The sum from start to end + */ + public long query(int start, int end) { + return queryHelper(root, start, end); + } + + public long queryHelper(SegmentSumTreeNode root, int start, int end){ + if (start > end) { + return 0; + } else if (root.start == start && root.end == end) { + return root.sum; + } + int mid = (root.start + root.end)/2; + if (end <= mid) { + return queryHelper(root.left, start, end); + } else if (start > mid) { + return queryHelper(root.right, start, end); + } + return queryHelper(root.left, start, root.left.end) + queryHelper(root.right, root.right.start, end); + } + + /** + * @param index, value: modify A[index] to value. + */ + public void modify(int index, int value) { + modifyHelper(root, index, value); + } + + public void modifyHelper(SegmentSumTreeNode node, int index, int value) { + if (node.start == index && node.end == index) { + node.sum = value; + return; + } + int mid = (node.start + node.end)/2; + if (index <= mid) { + modifyHelper(node.left, index, value); + } else { + modifyHelper(node.right, index, value); + } + node.sum = node.left.sum + node.right.sum; + } + + +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Interval Sum.java b/Others/old records/LintCode-Backup/Interval Sum.java new file mode 100644 index 0000000..0e18dfe --- /dev/null +++ b/Others/old records/LintCode-Backup/Interval Sum.java @@ -0,0 +1,109 @@ +其实是segment tree 每个node上面加个sum。 +构建tree记得怎么弄就好了。很简单的。 +但是,我犯了错..在search的时候求mid时,忘记了以root为基准(我用interval.start and interval.end为基准,当然错了) +但实际上search起来就是binary search的想法,在interval/segment tree上面跑。顺顺哒。 +``` +/* + +Given an integer array (index from 0 to n-1, where n is the size of this array), and an query list. Each query has two integers [start, end]. For each query, calculate the sum number between index start and end in the given array, return the result list. + +Example +For array [1,2,7,8,5], and queries [(0,4),(1,2),(2,4)], return [23,9,20] + +Note +We suggest you finish problem Segment Tree Build, Segment Tree Query and Segment Tree Modify first. + +Challenge +O(logN) time for each query +*/ + +/* + Thoughts: + Feels like constructing segment tree, and attach 'interval sum' to each node, after conquer its left and right child's sum. +*/ + +/** + * Definition of Interval: + * public classs Interval { + * int start, end; + * Interval(int start, int end) { + * this.start = start; + * this.end = end; + * } + */ +public class Solution { + public class SegmentSumTreeNode { + public int start, end; + public long sum; + public SegmentSumTreeNode left,right; + public SegmentSumTreeNode(int start, int end, long sum) { + this.start = start; + this.end = end; + this.sum = sum; + this.left = null; + this.right = null; + } + } + + public SegmentSumTreeNode buildTree(int[] A, int start, int end) { + if (start == end) { + return new SegmentSumTreeNode(start, end, A[start]); + } + int mid = (start + end)/2; + SegmentSumTreeNode leftChild = buildTree(A, start, mid); + SegmentSumTreeNode rightChid = buildTree(A, mid + 1, end); + + SegmentSumTreeNode node = new SegmentSumTreeNode(start, end, leftChild.sum + rightChid.sum); + node.left = leftChild; + node.right = rightChid; + + return node; + } + + public long searchTree(SegmentSumTreeNode root, int start, int end) { + if (root.start == start && root.end == end) { + return root.sum; + } + int mid = (root.start + root.end)/2; + if (end <= mid) { + return searchTree(root.left, start, end); + } else if (start > mid) { + return searchTree(root.right, start, end); + } + //start <= mid < end + return searchTree(root.left, start, root.left.end) + searchTree(root.right, root.right.start, end); + } + + /** + *@param A, queries: Given an integer array and an query list + *@return: The result list + */ + public ArrayList intervalSum(int[] A, ArrayList queries) { + ArrayList rst = new ArrayList(); + if (A == null || A.length == 0 || queries == null || queries.size() == 0) { + return rst; + } + SegmentSumTreeNode root = buildTree(A, 0, A.length - 1); + + for (Interval range : queries) { + long sum = 0; + /* + //Check for errors, but don't have to do these checks + //Well, it's being checked in segment query II + if (range.start < root.start && range.end > root.end) { + sum = root.sum; + } else if (range.start < root.start && range.end <= root.end) { + sum = searchTree(root, root.start, range.end); + } else if (range.start >= root.start && range.end > root.end) { + sum = searchTree(root, range.start, root.end); + } else { + sum = searchTree(root, range.start, range.end); + }*/ + sum = searchTree(root, range.start, range.end); + rst.add(sum); + } + return rst; + } + +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Invert Binary Tree.java b/Others/old records/LintCode-Backup/Invert Binary Tree.java new file mode 100644 index 0000000..181aa0d --- /dev/null +++ b/Others/old records/LintCode-Backup/Invert Binary Tree.java @@ -0,0 +1,82 @@ +/* +Invert a binary tree. + +Example + 1 1 + / \ / \ +2 3 => 3 2 + / \ + 4 4 +Challenge +Do it in recursion is acceptable, can you do it without recursion? + +Tags Expand +Binary Tree + +Thoughts: +1. Swap every node's left and right child. Recursion seems good. + +2. If not recursion, can use a queue to keep track of nodes. Keep swapping until the queue +is processed. +*/ + + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: a TreeNode, the root of the binary tree + * @return: nothing + */ + public void invertBinaryTree(TreeNode root) { + if (root == null) { + return; + } + Queue queue = new LinkedList(); + queue.offer(root); + while(!queue.isEmpty()) { + TreeNode node = queue.poll(); + TreeNode temp = node.left; + node.left = node.right; + node.right = temp; + if (node.left != null) { + queue.offer(node.left); + } + if (node.right != null) { + queue.offer(node.right); + } + } + } +} + + +//Now, solution 2, try recursion. +public class Solution { + /** + * @param root: a TreeNode, the root of the binary tree + * @return: nothing + */ + public void invertBinaryTree(TreeNode root) { + if (root == null) { + return; + } + TreeNode temp = root.left; + root.left = root.right; + root.right = temp; + + invertBinaryTree(root.left); + invertBinaryTree(root.right); + } +} + + + diff --git a/Others/old records/LintCode-Backup/Jump Game II.java b/Others/old records/LintCode-Backup/Jump Game II.java new file mode 100644 index 0000000..26720f0 --- /dev/null +++ b/Others/old records/LintCode-Backup/Jump Game II.java @@ -0,0 +1,57 @@ +/* +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Your goal is to reach the last index in the minimum number of jumps. + +Example +Given array A = [2,3,1,1,4] + +The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.) + +Tags Expand +Greedy Array + +Thanks to Yu’s Garden blog +Thinking process: +0. Use two pointers pStart and pEnd to track the potential locations we can move to. +Consider a range from current spot to the farthest spot: try to find a max value from this range, and see if the max can reach the tail of array. +If no max can read the tail of array, that means we need to move on. At this point, let pStart = pEnd + 1. At same time, move pEnd to the max spot we can go to. Since pEnd moves forward, we could step++ +If max reach the tail of array, return the steps. +*/ + +public class Solution { + /** + * @param A: A list of lists of integers + * @return: An integer + */ + public int jump(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int pStart = 0; + int pEnd = 0; + int steps = 0; + while (pEnd < A.length - 1) { + steps++; //Cound step everytime when pEnd is moving to the farthest. + int farthest = 0; + //Find farest possible and see if reach the tail + for (int i = pStart; i <= pEnd; i++) { + farthest = Math.max(farthest, i + A[i]); + if (farthest >= A.length - 1) { + return steps; + } + } + //Re-select pointer position for start and end + pStart = pEnd + 1; + pEnd = farthest; + } + return -1; //This is the case where no solution can be found. + } +} + + +//Also DP from nineChapter: +http://www.ninechapter.com/solutions/jump-game-ii/ + diff --git a/Others/old records/LintCode-Backup/Jump Game.java b/Others/old records/LintCode-Backup/Jump Game.java new file mode 100644 index 0000000..53664b9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Jump Game.java @@ -0,0 +1,82 @@ +/* +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Determine if you are able to reach the last index. + +Example +A = [2,3,1,1,4], return true. + +A = [3,2,1,0,4], return false. + +This can be done using DP. However, greedy algorithm is fast in this particular problem. Consider both solutions. + +DP +Thinking Process: +We have array A, that stores the # of steps for each index. +State: f[i] means if previous steps can reach to i. True/False +Function: f[i] = f[j] && (j + A[j] >= i) +Init: f[0] = true +Answer: f[n-1], if n is the length of A +*/ + +public class Solution { + /** + * @param A: A list of integers + * @return: The boolean answer + **/ + //DP + public boolean canJump(int[] A) { + if (A == null || A.length == 0) { + return false; + } + //By default, boolean[] can is all false + boolean[] can = new boolean[A.length]; + can[0] = true; + for (int i = 1; i < A.length; i++) { + for (int j = 0; j < i; j++) { + if (A[j] && (j + A[j] >= i)) { + can[i] = true; + break; + } + } + } + return can[A.length - 1]; + } +} + + + +/* + +Greedy. Ideas from Yu’s Garden +At each index, check how far we can jump, store this forest-can-jump position in variable ‘farest’. Take max of current farest and (index + A[index]), store is in farest +At each index, compare if ‘farest’ is greater than the end of array, if so, found solution, return true. +At each index, also check if ‘farest == current index’, that means the farest we can move is to current index and we cannot move forward. Then return false. +*/ + +public class Solution { + /** + * @param A: A list of integers + * @return: The boolean answer + **/ + + public boolean canJump(int[] A) { + if (A == null || A.length == 0) { + return false; + } + int farest = 0; + for (int i = 0; i < A.length; i++) { + farest = Math.max(farest, i + A[i]); + if (farest > A.length - 1) { + return true; + } + if (farest == i) { + return false; + } + } + return true; + } +} + diff --git a/Others/old records/LintCode-Backup/Kth Largest Element.java b/Others/old records/LintCode-Backup/Kth Largest Element.java new file mode 100644 index 0000000..42bf011 --- /dev/null +++ b/Others/old records/LintCode-Backup/Kth Largest Element.java @@ -0,0 +1,91 @@ +/* +Find K-th largest element in an array. + +Example +In array [9,3,2,4,8], the 3rd largest element is 4 + +In array [1,2,3,4,5], the 1st largest element is 5, 2nd largest element is 4, 3rd largest element is 3 and etc. + +Note +You can swap elements in the array + +Challenge +O(n) time, O(1) space + +Tags Expand +Quick Sort Sort + +Thoughts: +Almost the same as the Median problem: +the only difference is, this one is not looking for the middle point, but for the last kth element. +Using the same quick sort code with minor modifications, and we can solve this problem. +*/ + + +class Solution { + //param k : description of k + //param numbers : array of numbers + //return: description of return + public int kthLargestElement(int k, ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + return helper(nums, 0, nums.size() - 1, nums.size() - k); + } + + public void swap( ArrayListnums, int x, int y){ + int temp = nums.get(x); + nums.set(x, nums.get(y)); + nums.set(y, temp); + } + + public int helper( ArrayList nums, int start, int end, int mid) { + int pivot = end; + int num = nums.get(pivot); + int low = start; + int high = end; + while (low < high) { + while(low < high && nums.get(low) < num) { + low++; + } + while(low < high && nums.get(high) >= num) { + high--; + } + swap(nums, low, high); + } + swap(nums, low, pivot); + if (low == mid) { + return nums.get(low); + } else if (low < mid) { + return helper(nums, low + 1, end, mid); + } else { + return helper(nums, start, low - 1, mid); + } + } +}; + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Kth Smallest Sum In Two Sorted Arrays.java b/Others/old records/LintCode-Backup/Kth Smallest Sum In Two Sorted Arrays.java new file mode 100644 index 0000000..1f14c84 --- /dev/null +++ b/Others/old records/LintCode-Backup/Kth Smallest Sum In Two Sorted Arrays.java @@ -0,0 +1,94 @@ +挺勇猛. 还好网上有个题目是找kth最大。 +用priority queue. 每次把最小的展开,移位。分别x+1,或者y+1。 +因为当下的Min里面x,y都是最小的。所以下一个最小的不是(x+1,y),就是(x,y+1)。当然,放在PriorityQueue里面的原因就是,很可能跟之前在queue里面的pair产生比较。 +每次就poll()一个,放新candidate进去就好了。 +注意,这样的做法会用重复,比如例子(7,4)会出现两次。用一个HashSet挡一下。 + +学会用priorityqueue. + +注意,HashSet的唯一性,用一个"x,y"的string就可以代为解决。 +``` +/* +Given two integer arrays sorted in ascending order and an integer k. Define sum = a + b, where a is an element from the first array and b is an element from the second one. Find the kth smallest sum out of all possible sums. + +Example +Given [1, 7, 11] and [2, 4, 6]. + +For k = 3, return 7. + +For k = 4, return 9. + +For k = 8, return 15. + +Challenge +Do it in either of the following time complexity: + +1. O(k log min(n, m, k)). where n is the size of A, and m is the size of B. +2. O( (m + n) log maxValue). where maxValue is the max number in A and B. +Tags Expand +Heap Priority Queue Sorted Matrix + +*/ +//NOT DONE +/* + Thoughts: + Inspired by:http://stackoverflow.com/questions/5212037/find-the-pair-across-2-arrays-with-kth-largest-sum + + User a priority queue and sort based on the smallest sum + Add k-1 times into the heap. Each time poll the smallest and expand. + Finally poll the top of the heap, which will be the smallest + + Note: There will be duplicates,so use a hashstet to mark duplicates. Becareful with what we put int hashset. +*/ +public class Solution { + public class Point{ + int x,y, val; + public Point(int x, int y, int val) { + this.x = x; + this.y = y; + this.val = val; + } + } + + public int kthSmallestSum(int[] A, int[] B, int k) { + if (A == null || B == null || A.length == 0 || B.length == 0 || k < 0) { + return -1; + } + PriorityQueue queue = new PriorityQueue(2, new Comparator(){ + public int compare(Point p1, Point p2) { + return p1.val - p2.val; + } + }); + HashSet set = new HashSet(); + Point min = new Point(0, 0, A[0] + B[0]); + queue.offer(min); + set.add(min.x + "," + min.y); + + int n = A.length; + int m = B.length; + + for (int i = 0; i < k - 1; i++) { + min = queue.poll(); + + if (min.x + 1 < n) { + Point newP = new Point(min.x + 1, min.y, A[min.x + 1] + B[min.y]); + if (!set.contains(newP.x + "," + newP.y)) { + set.add(newP.x + "," + newP.y); + queue.offer(newP); + } + } + if (min.y + 1 < m) { + Point newP = new Point(min.x, min.y + 1, A[min.x] + B[min.y + 1]); + if (!set.contains(newP.x + "," + newP.y)) { + set.add(newP.x + "," + newP.y); + queue.offer(newP); + } + } + } + + min = queue.poll(); + return min.val; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Largest Number.java b/Others/old records/LintCode-Backup/Largest Number.java new file mode 100644 index 0000000..c88247c --- /dev/null +++ b/Others/old records/LintCode-Backup/Largest Number.java @@ -0,0 +1,64 @@ +/* +Given a list of non negative integers, arrange them such that they form the largest number. + +Example +Given [1, 20, 23, 4, 8], the largest formed number is 8423201. + +Note + The result may be very large, so you need to return a string instead of an integer. + +Tags Expand +Sort + +Thoughts: +Use a comparator with String.comareTo, then uset Arrays.sort(...) + +*/ + +class CustomComparator implements Comparator { + public int compare(String s1, String s2) { + return (s2 + s1).compareTo(s1 + s2); + } +} +public class Solution { + /** + *@param num: A list of non negative integers + *@return: A string + */ + public String largestNumber(int[] num) { + if (num == null || num.length == 0) { + return ""; + } + String[] strs = new String[num.length]; + for (int i = 0; i < num.length; i++) { + strs[i] = num[i] + ""; + } + Arrays.sort(strs, new CustomComparator()); + StringBuffer sb= new StringBuffer(); + for (int i = 0; i < num.length; i++) { + sb.append(strs[i]); + } + String rst = sb.toString(); + if (rst.charAt(0) == '0') { + return "0"; + } + return rst; + } +} + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Largest Rectangle in Histogram.java b/Others/old records/LintCode-Backup/Largest Rectangle in Histogram.java new file mode 100644 index 0000000..4f2f6a8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Largest Rectangle in Histogram.java @@ -0,0 +1,37 @@ +/* +Example +Given height = [2,1,5,6,2,3], +return 10. + +Tags Expand +Array Stack + +Thinking Process: +///TODO: missing thinking process for Largest Rectangle in Histogram + +*/ + +public class Solution { + /** + * @param height: A list of integer + * @return: The area of largest rectangle in the histogram + */ + public int largestRectangleArea(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + Stack stack = new Stack(); + int max = 0; + for (int i = 0; i <= height.length; i++) { + int current = (i == height.length) ? -1 : height[i]; + while (!stack.empty() && current <= height[stack.peek()]) { + int h = height[stack.pop()]; + int w = stack.empty() ? i : i - stack.peek() - 1; + max = Math.max(max, w * h); + } + stack.push(i); + } + return max; + } +} + diff --git a/Others/old records/LintCode-Backup/Last Position of Target.java b/Others/old records/LintCode-Backup/Last Position of Target.java new file mode 100644 index 0000000..236c6f0 --- /dev/null +++ b/Others/old records/LintCode-Backup/Last Position of Target.java @@ -0,0 +1,64 @@ +``` +有重复,不是末尾点,继续binary search +/* +Find the last position of a target number in a sorted array. Return -1 if target does not exist. + +Example +Given [1, 2, 2, 4, 5, 5]. + +For target = 2, return 2. + +For target = 5, return 5. + +For target = 6, return -1. + +Tags Expand +Binary Search +*/ + +/* + Thoughts: + Regular binary search for it. + found condition: A[mid] == target && A[mid + 1] != target + +*/ +public class Solution { + /** + * @param A an integer array sorted in ascending order + * @param target an integer + * @return an integer + */ + public int lastPosition(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + int start = 0; + int end = A.length - 1; + int mid; + + while(start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + if (mid + 1 < A.length && A[mid + 1] == target) { + start = mid; + } else { + return mid; + } + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + + if (A[end] == target) { + return end; + } else if (A[start] == target) { + return start; + } + + return -1; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Length of Last Word.java b/Others/old records/LintCode-Backup/Length of Last Word.java new file mode 100644 index 0000000..4f478bb --- /dev/null +++ b/Others/old records/LintCode-Backup/Length of Last Word.java @@ -0,0 +1,38 @@ +/* +Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. + +If the last word does not exist, return 0. + +Example +Given s = "Hello World", return 5. + +Note +A word is defined as a character sequence consists of non-space characters only. + +Tags Expand +String + +Thoughts: +1. Split by space +2. return last word's length + +Note: Java split: have to add '\\' in order to pass the key word. +*/ + + + +public class Solution { + /** + * @param s A string + * @return the length of last word + */ + public int lengthOfLastWord(String s) { + if (s == null || s.length() == 0) { + return 0; + } + String[] arr = s.split("\\ "); + String lastWord = arr[arr.length - 1]; + + return lastWord.length(); + } +} diff --git a/Others/old records/LintCode-Backup/Letter Combinations of a Phone Number.java b/Others/old records/LintCode-Backup/Letter Combinations of a Phone Number.java new file mode 100644 index 0000000..bbda83e --- /dev/null +++ b/Others/old records/LintCode-Backup/Letter Combinations of a Phone Number.java @@ -0,0 +1,150 @@ +/* +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. + +Cellphone. Picture:http://www.lintcode.com/en/problem/letter-combinations-of-a-phone-number/ + +Example +Given "23" + +Return ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"] + +Note +Although the above answer is in lexicographical order, your answer could be in any order you want. + +Tags Expand +String Backtracking Recursion Facebook Uber +*/ + +/* + Thoughts: have done this on Leetcode. + map integer to letters + combination of existing letters (by pressing fist number) with next number's letters. + put combinations into queue, reuse the queue. + finally, output into arraylist + + NON-recursive/iterative: use a queue. (Done this one Leetcode) + + This time, use recursive: + pass along rst, list, level number, digits, + for (combine list with all next level's candidates, map) + when level number == digits.length(), return the candidate into rst. +*/ +public class Solution { + /** + * @param digits A digital string + * @return all posible letter combinations + */ + public ArrayList letterCombinations(String digits) { + ArrayList rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + ArrayList map = new ArrayList(); + map.add(new String[]{});//key 0: nothing + map.add(new String[]{});//key 1: nothing + map.add(new String[]{"a","b","c"}); + map.add(new String[]{"d","e","f"}); + map.add(new String[]{"g","h","i"}); + map.add(new String[]{"j","k","l"}); + map.add(new String[]{"m","n","o"}); + map.add(new String[]{"p","q","r","s"}); + map.add(new String[]{"t","u","v"}); + map.add(new String[]{"w","x","y","z"}); + + ArrayList list = new ArrayList(); + helper(rst, list, map, digits, 0); + + return rst; + } + + public void helper(ArrayList rst, ArrayList list, + ArrayList map, String digits, int level){ + //If level is finished, compress into string + if (level == digits.length()) { + StringBuffer sb = new StringBuffer(); + for (String s : list) { + sb.append(s); + } + rst.add(sb.toString()); + return; + } + //For a specific list of candidates, face the level of chars + int num = Integer.parseInt(digits.substring(level, level + 1)); + String[] strs = map.get(num); + + for (int i = 0; i < strs.length; i++) { + list.add(strs[i]); + helper(rst, list, map, digits, level + 1); + list.remove(list.size() - 1); + } + } + +} + + + + + + + +//Iterative: +//Use 1 queue +// and optimize a bit +public class Solution { + public List letterCombinations(String digits) { + List rst = new ArrayList(); + if (digits == null || digits.length() == 0) { + return rst; + } + HashMap map = new HashMap(); + map.put(2, "abc");map.put(3, "def"); + map.put(4, "ghi");map.put(5, "jkl");map.put(6, "mno"); + map.put(7, "pqrs");map.put(8,"tuv");map.put(9,"wxyz"); + + Queue queue = new LinkedList(); + + //init + int index = 0; + int digit = Integer.parseInt(digits.substring(index, index + 1)); + String keys = map.get(digit); + index++; + + for (int i = 0; i < keys.length(); i++) { + queue.offer(keys.substring(i,i+1)); + } + int size = queue.size(); + + while (index < digits.length() && !queue.isEmpty()) { + String str = queue.poll(); + digit = Integer.parseInt(digits.substring(index, index + 1)); + keys = map.get(digit); + for (int i = 0; i < keys.length(); i++) { + queue.offer(str + keys.substring(i,i+1)); + } + size--; + if (size == 0 && index < digits.length() - 1) { + index++; + size = queue.size(); + } + }//end while + + while (!queue.isEmpty()) { + rst.add(queue.poll()); + } + + return rst; + } +} + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Linked List Cycle II.java b/Others/old records/LintCode-Backup/Linked List Cycle II.java new file mode 100644 index 0000000..a4501f5 --- /dev/null +++ b/Others/old records/LintCode-Backup/Linked List Cycle II.java @@ -0,0 +1,115 @@ +HashMap很简单就做了。 + + +O(1)要首先break while loop when there is a slow==fast +然后,然后就有个我不懂得地方: + +当head == slow.next时候, head就是cycle starting point. +也就是说,当slow 移动到了那个回溯点,slow.next那个点就刚好是head的那个点... + +这个可能要写一写,装一装,证明证明才行...不是特别清楚。 +``` +/* +Given a linked list, return the node where the cycle begins. + +If there is no cycle, return null. + +Example +Given -21->10->4->5, tail connects to node index 1,return 10 + +Challenge +Follow up: + +Can you solve it without using extra space? + +Tags Expand +Two Pointers Linked List + +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +/* + + Thoughts: 12.10.2015 + Note sure why Lintcode says it's hard. Now try to do both: + 1. HashMap + 2. Slow/Fast pointer + + Note: The linkNode is not necessary unique. They can have diffeent values, but as long as they are + not on same physical address, no cycle. + That is: it's all about index, rather than the value. + + SO: if we do hashmap, we are hasing the entire ListNode object, so whenever there is duplicate, + that is a match. + + Rather: if we do slow/fast pointer, +*/ + +//HashMap +public class Solution { + public ListNode detectCycle(ListNode head) { + if (head == null) { + return null; + } + + HashMap map = new HashMap();//Does not matter of the value + while (head != null) { + if (map.containsKey(head)) { + return head; + } else { + map.put(head, head.val); + } + head = head.next; + } + + return null; + } +} + + +//Slow/Fast Pointer +//http://www.jiuzhang.com/solutions/linked-list-cycle-ii/ +/* + 1. just like in Linked List Cycle. Keep looking. If found a slow==fast, break the 1st while loop. + + 2. At that moment, the slow is not the cycle starting point. We need to look for it + There must be some proof within the 2nd step, which i dont know. SO, need sort of remember it: + When head == slow.next, then head is the cycle starting point .... + (not exactly sure why. I guess this is why it's a hard question) + +*/ +public class Solution { + public ListNode detectCycle(ListNode head) { + if (head == null) { + return null; + } + ListNode slow = head; + ListNode fast = head.next; + while (slow != fast) { + if (fast == null || fast.next == null) { + return null; + } + slow = slow.next; + fast = fast.next.next; + } + + while (head != slow.next) { + slow = slow.next; + head = head.next; + } + + return head; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Linked List Cycle.java b/Others/old records/LintCode-Backup/Linked List Cycle.java new file mode 100644 index 0000000..5a87d8d --- /dev/null +++ b/Others/old records/LintCode-Backup/Linked List Cycle.java @@ -0,0 +1,96 @@ +O(1) sapce: 用快慢指针。一个跑.next, 一个跑.next.next。 总有一次,fast会因为cycle而追上slow。 +那个时候其实slow.val = fast.val. + +O(n):用HashMap,一直add elements. 如果有重复,那么很显然是有Cycle le +``` +/* +50% Accepted +Given a linked list, determine if it has a cycle in it. + + + +Example +Challenge +Follow up: +Can you solve it without using extra space? + +Tags Expand +Linked List Two Pointers + +*/ + + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ + +/* + REDO 12.10.2015 + Rulese for fast/slow pointer: + 1. move slow and fast, + 2. See if the object address matches + + IMPORTANT: do not compare the value, because they didn't say value has to be unique. + Even with same value, the ListNode object can be different at different index. +*/ + +public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null || head.next == null) { + return false; + } + ListNode slow = head; + ListNode fast = head.next; + + while (slow != fast) {//Compare their reference address + if (fast == null || fast.next == null) {//travel till the end + return false;//no cycle + } + slow = slow.next; + fast = fast.next.next; + } + //If slow==fast and breaks the while loop, then there must be a cycle + return true; + } +} + + +/* +Thinking process: +If there is a cycle, then slow node and fast node will meet at some point. + + +However, we cannot simply compare slow.val == fast.val. +This is because, there can be different link node with same value, but they are stored on different index, +so they should not be cycle. + +The below passes the test case in lintcode, which is wrong. + +public class Solution { + public boolean hasCycle(ListNode head) { + if (head == null) { + return false; + } + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + if (slow.val == fast.val) { + return true; + } + slow = slow.next; + fast = fast.next.next; + } + return false; + } +} +*/ + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Common Prefix.java b/Others/old records/LintCode-Backup/Longest Common Prefix.java new file mode 100644 index 0000000..c029d70 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Common Prefix.java @@ -0,0 +1,65 @@ +/* +Given k strings, find the longest common prefix (LCP). + +Example +For strings "ABCD", "ABEF" and "ACEF", the LCP is "A" + +For strings "ABCDEFG", "ABCEFG" and "ABCEFA", the LCP is "ABC" + +Tags Expand +Enumeration Basic Implementation String LintCode Copyright + +Thoughts: +1. Continuous while loop until something breaks out. +2. Str to record the longest prefix +3. for loop on each while-loop, based on strs[0] + Check if index exist + check if all other strs have same char at this point. If so, add it. If not, break. + +Note: +Arrays: use strs.length +String: use str.length(). +Odd, right? I know ... dislike. +String seems to be supirior, it's a god damn object, and we have a method for checking string length. +For array, well, looks like it's been mistreated ... we are only reading a length property of the array object. + +Note2: +Ask for border case: when only 1 string, longest prefix turns out it's the strs[0] itself. +*/ + + +public class Solution { + /** + * @param strs: A list of strings + * @return: The longest common prefix + */ + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + if (strs.length == 1) { + return strs[0]; + } + String prefix = ""; + int ind = 0; + while (ind < strs[0].length()) { + char c = strs[0].charAt(ind); + boolean valid = false; + for (int i = 1; i < strs.length; i++) { + if (strs[i].length() > ind && strs[i].charAt(ind) == c) { + valid = true; + } else { + valid = false; + break; + } + } + if (valid) { + prefix += "" + c; + } else { + break; + } + ind++; + }//END WHILE + return prefix; + } +} \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Common Subsequence.java b/Others/old records/LintCode-Backup/Longest Common Subsequence.java new file mode 100644 index 0000000..f423e2f --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Common Subsequence.java @@ -0,0 +1,53 @@ +/* +Given two strings, find the longest comment subsequence (LCS). + +Your code should return the length of LCS. + +Example +For "ABCD" and "EDCA", the LCS is "A" (or D or C), return 1 + +For "ABCD" and "EACB", the LCS is "AC", return 2 + +Clarification +What's the definition of Longest Common Subsequence? + + * The longest common subsequence (LCS) problem is to find the longest subsequence common to all sequences in a set of sequences (often just two). (Note that a subsequence is different from a substring, for the terms of the former need not be consecutive terms of the original sequence.) It is a classic computer science problem, the basis of file comparison programs such as diff, and has applications in bioinformatics. + + * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem + +Tags Expand +LintCode Copyright Longest Common Subsequence Dynamic Programming + +Thinking process: +Using DP. +check[i][j] means: the length of longest common subsequnce between A(0 ~ i) and B(0 ~ j). +Then there are two ways to reach check[i][j]: +1. A(i-1) == B(j - 1), then check[i][j] = check[i - 1][j - 1] + 1; +2. A(i-1) != B(j - 1), then pick the max between (i-1,j) , (i,j-1) and (i, j ) +Note: check[][] is initialized with all 0's. Index (0,0) is used as starting 0. +*/ +public class Solution { + /** + * @param A, B: Two strings. + * @return: The length of longest common subsequence of A and B. + */ + public int longestCommonSubsequence(String A, String B) { + if (A == null || B == null || A.length() == 0 || B.length() == 0) { + return 0; + } + int[][] check = new int[A.length() + 1][B.length() + 1]; + for (int i = 1; i <= A.length(); i++) { + for (int j = 1; j <= B.length(); j++) { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + check[i][j] = check[i - 1][j - 1] + 1; + } else { + check[i][j] = Math.max(check[i][j], check[i - 1][j]); + check[i][j] = Math.max(check[i][j], check[i][j - 1]); + } + } + } + return check[A.length()][B.length()]; + } +} + + diff --git a/Others/old records/LintCode-Backup/Longest Common Substring.java b/Others/old records/LintCode-Backup/Longest Common Substring.java new file mode 100644 index 0000000..62d320c --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Common Substring.java @@ -0,0 +1,56 @@ +/* +Given two strings, find the longest common substring. + +Return the length of it. + +Example +Given A = "ABCD", B = "CBCE", return 2. + +Note +The characters in substring should occur continuously in original string. This is different with subsequence. + +Challenge +O(n x m) time and memory. + +Tags Expand +LintCode Copyright Longest Common Subsequence Dynamic Programming + +Thoughts: +1. Compare all i X j. +2. Use a D[i][j] to mark the amount of common substring based on D[i - 1][j -1]. Could be 0. +3. track max length + +NOTE1: create 2D array that's [N + 1][M + 1] because we want to hold D[n][M] in the 2d array +NOTE2: be carefule with init index 0's + +*/ + + +public class Solution { + /** + * @param A, B: Two string. + * @return: the length of the longest common substring. + */ + public int longestCommonSubstring(String A, String B) { + if (A == null || B == null || A.length() == 0 || B.length() == 0) { + return 0; + } + int [][] D = new int[A.length() + 1][B.length() + 1]; + int max = 0; + for (int i = 0; i <= A.length(); i++) { + for(int j = 0; j <= B.length(); j++) { + if (i == 0 || j == 0) { + D[i][j] = 0; + } else { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + D[i][j] = D[i - 1][j - 1] + 1; + } else { + D[i][j] = 0; + } + max = Math.max(max, D[i][j]); + } + } + } + return max; + } +} diff --git a/Others/old records/LintCode-Backup/Longest Consecutive Sequence.java b/Others/old records/LintCode-Backup/Longest Consecutive Sequence.java new file mode 100644 index 0000000..19f3b02 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Consecutive Sequence.java @@ -0,0 +1,99 @@ +/* +Given an unsorted array of integers, find the length of the longest consecutive elements sequence. + +For example, +Given [100, 4, 200, 1, 3, 2], +The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. + +Your algorithm should run in O(n) complexity. + +Hide Tags Array + +Thinking process: +0. This problem can be done using sorting, but time complexity of sorting is O(nlogn). This problem requires O(n). +1. Want to check if a number's left and right is consecutive to itself, but cannot do it due to the given unsorted array: think about a Hashmap. +2. HashMap(Key, Value) = (the number itself, boolean: have been counted or not). If you count a number as a consecutive, you only need to count it once. +3. How HashMap works: + when checking a number's consecutive, look at number--, number++, see if they are in the HashMap. If exist, means consecutive. + If a number exist in the hashmap and its value is 'true', then we need to skip this number beacuse it has been checked. +4. Track the total number consecutives of 1 perticular number, compare it with the maxL. Save the Math.max to maxL. +5. Depending on the problem, we can store a consecutive sequence or simply just its length: maxL. This problem wants the maxL. +*/ + +public class Solution { + public int longestConsecutive(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + int maxL = 1; + HashMap history = new HashMap(); + for (int i : num) { + history.put(i, false); + } + for (int i : num) { + if (history.get(i)) { + continue; + } + //check ++ side + int temp = i; + int total = 1; + while (history.containsKey(temp + 1)) { + total++; + temp++; + history.put(temp, true); + } + //check -- side + temp = i; + while (history.containsKey(temp - 1)) { + total++; + temp--; + history.put(temp, true); + } + maxL = Math.max(maxL, total); + } + return maxL; + } +} + + + +/* +10.19.2015 +Thougths: +1. sort +2. use a 'count' and 'max' to keep track of consecutive elements +3. one-pass + +Note: +Take care of equal numbers: skip/continue those + +*/ + +public class Solution { + /** + * @param nums: A list of integers + * @return an integer + */ + public int longestConsecutive(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + if (num.length == 1) { + return 1; + } + int count = 1; + int max = 1; + Arrays.sort(num); + for (int i = 1; i < num.length; i++) { + if (num[i - 1] == num[i]) { + continue; + } else if (num[i - 1] + 1 == num[i]) { + count++; + max = Math.max(count, max); + } else { + count = 1; + } + } + return max; + } +} diff --git a/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence II.java b/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence II.java new file mode 100644 index 0000000..f8b6ecf --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence II.java @@ -0,0 +1,84 @@ +O(mn) space for dp and flag. +O(mn) runtime because each spot will be marked once visited. +这个题目的简单版本一个array的例子:从简单题目开始想DP会简单一点。每个位置,都是从其他位置(上下左右)来的dpValue + 1. 如果啥也没有的时候,init state 其实都是1, 就一个数字,不增不减嘛。 +``` +/* +Give you an integer matrix (with row size n, column size m),find the longest increasing continuous subsequence in this matrix. (The definition of the longest increasing continuous subsequence here can start at any row or column and go up/down/right/left any direction). + +Example +Given a matrix: + +[ + [1 ,2 ,3 ,4 ,5], + [16,17,24,23,6], + [15,18,25,22,7], + [14,19,20,21,8], + [13,12,11,10,9] +] +return 25 + +Challenge +O(nm) time and memory. + +Tags Expand +Dynamic Programming +*/ + +/* +Thoughts: +Similar to JiuZhang's DP in longest increasing continuous subsequence I. +Imagining values are coming from 4 directions so A[i][j] < A[dx][dy]. +State: +DP[i][j]: coming from 4 different directions, the longest we can get on DP[i][j]. +Use flag[i][j] to mark. 1: checked, return dp[i][j] directly; -1: marked, don't over going that direction +Fn: +Go 4 direcetions dfs. +Init: +Can init during dfs by giving a default value of 1 to each spot. +*/ +public class Solution { + /** + * @param A an integer matrix + * @return an integer + */ + public int longestIncreasingContinuousSubsequenceII(int[][] A) { + if (A == null || A.length == 0 || A[0].length == 0) { + return 0; + } + int n = A.length; + int m = A[0].length; + int[][] dp = new int[n][m]; + int[][] flag = new int[n][m]; + int ans = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + dp[i][j] = dfs(A, dp, flag, i, j, n, m); + ans = Math.max(ans, dp[i][j]); + } + } + return ans; + } + + public int dfs(int[][] A, int[][] dp, int[][] flag, int i, int j, int n, int m) { + if (flag[i][j] == 1) { + return dp[i][j]; + } + int ans = 1; + flag[i][j] = -1; + int[] dx = {0, 0, 1, -1}; + int[] dy = {1, -1, 0, 0}; + //Go 4 directions + for (int k = 0; k < dx.length; k++) { + int id = i + dx[k]; + int jd = j + dy[k]; + if (id >= 0 && id < n && jd >= 0 && jd < m && A[i][j] < A[id][jd]) { + ans = Math.max(ans, dfs(A, dp, flag, id, jd, n, m) + 1); + } + } + flag[i][j] = 1; + dp[i][j] = ans; + return dp[i][j]; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence.java b/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence.java new file mode 100644 index 0000000..24c7255 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Increasing Continuous subsequence.java @@ -0,0 +1,163 @@ +O(n)跑2遍for. +O(1)是用了两个int来存:每次到i点时,i点满足条件或不满足条件所有的longestIncreasingContinuousSubsequence. +特点:返跑一回,ans还是继续和left轮的ans作比较;求的所有情况的最大值嘛。 +``` +/* +Give you an integer array (index from 0 to n-1, where n is the size of this array),find the longest increasing continuous subsequence in this array. (The definition of the longest increasing continuous subsequence here can be from right to left or from left to right) +Example +For [5, 4, 2, 1, 3], the LICS is [5, 4, 2, 1], return 4. +For [5, 1, 2, 3, 4], the LICS is [1, 2, 3, 4], return 4. +Note +O(n) time and O(1) extra space. +Tags Expand +Dynamic Programming Array +*/ +/* +OPTS: O(n) time and O(1) space +Thoughts: not quite DP yet, but used 1 leftRun/rightRun to store status, sort of DP. +*/ +public class Solution { + /** + * @param A an array of Integer + * @return an integer + */ + public int longestIncreasingContinuousSubsequence(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int leftRun = 1; + int rightRun = 1; + int ans = 1; + for (int i = 1; i < A.length; i++) { + if (A[i] > A[i - 1]) { + leftRun++; + } else { + leftRun = 1; + } + ans = Math.max(ans, leftRun); + } + for (int i = A.length - 2; i >= 0; i--) { + if (A[i] > A[i + 1]) { + rightRun++; + } else { + rightRun = 1; + } + ans = Math.max(ans, rightRun); + } + return ans; + } +} +``` + + +九章的DP,没有用O(1)space,但是应该是为这道题的followup做准备的模式。 +用dp和dfs. +每次dfs左右时都要mark一下flag,防止重跑 +``` +/* +Thoughts: JiuZhang's DP. +dp[i]: longest increasing continous subsequence on i, regardless if the sequence is incresing from left or right. +Use flag[i] to mark if a position has been visited. If visited (flag == 1), then immediately return dp[i] since we've calculated this before. +Note. Also mark flag[i] == -1 in each dfs interation, to prevent redudant looping (infinite loop) + +Stackover flow at 96%. +*/ +public class Solution { + /** + * @param A an array of Integer + * @return an integer + */ + public int longestIncreasingContinuousSubsequence(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int[] dp = new int[A.length]; + int[] flag = new int[A.length]; + int ans = 0; + for (int i = 0; i < A.length; i++) { + dp[i] = dfs(A, dp, flag, i); + ans = Math.max(ans, dp[i]); + } + return ans; + } + + public int dfs(int[] A, int[] dp, int[] flag, int i){ + if (flag[i] == 1) { + return dp[i]; + } + int ansLeft = 1; + int ansRight = 1; + flag[i] = -1; + //Increasing from left->right + if (i - 1 >= 0 && A[i - 1] < A[i] && flag[i - 1] != -1) { + ansLeft = dfs(A, dp, flag, i - 1) + 1; + } + //Increasing from right->left + if (i + 1 < A.length && A[i] > A[i + 1] && flag[i + 1] != -1) { + ansRight = dfs(A, dp, flag, i + 1) + 1; + } + flag[i] = 1; + dp[i] = Math.max(ansLeft, ansRight); + return dp[i]; + } +} + + + + +``` + + + + + + + +老码 +``` +/* +Older approach. Longer code :( +Thoughts: +1. Reverse search for the same int[] A. + In 1,2 keep track of maxLength1. maxLength2 +2. Compare maxLength, and use the largest +Note: +After for loop, need to catch the very last comparison, to get result of track ;) + +*/ +//[5,4,2,1,3] +public class Solution { + /** + * @param A an array of Integer + * @return an integer + */ + public int longestIncreasingContinuousSubsequence(int[] A) { + if (A == null || A.length == 0) { + return -1; + } + int maxLength1 = 0; + int maxLength2 = 0; + int track = 1; + for (int i = 1; i < A.length; i++) { + if (A[i] > A[i - 1]) { + track++; + } else { + maxLength1 = track > maxLength1 ? track : maxLength1; + track = 1; + } + } + maxLength1 = track > maxLength1 ? track : maxLength1; + track = 1; + for (int i = A.length - 2; i >= 0; i--) { + if (A[i] > A[i + 1]) { + track++; + } else { + maxLength2 = track > maxLength2 ? track : maxLength2; + track = 1; + } + } + maxLength2 = track > maxLength2 ? track : maxLength2; + return maxLength1 > maxLength2 ? maxLength1 : maxLength2; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Increasing Subsequence.java b/Others/old records/LintCode-Backup/Longest Increasing Subsequence.java new file mode 100644 index 0000000..1299675 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Increasing Subsequence.java @@ -0,0 +1,90 @@ +i位和之前的0~i-1 都远关系。复杂一点。 +每次都考虑o~i的所有情况。所以double for loop +``` +/* +Given a sequence of integers, find the longest increasing subsequence (LIS). + +You code should return the length of the LIS. + +Example +For [5, 4, 1, 2, 3], the LIS is [1, 2, 3], return 3 + +For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4 + +Challenge +Time complexity O(n^2) or O(nlogn) + +Clarification +What's the definition of longest increasing subsequence? + + * The longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique. + + * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem + +Tags Expand +Binary Search LintCode Copyright Dynamic Programming +*/ + +/* + Thoughts: + dp[i] depends on not only dp[i-1], but also [i-1] ...[0]. + So it has to be double-for loop. + Each sub-for loop on i, traverse 0 ~ j(j<=i) to find largest number to put on dp[i] + fn: + dp[i] = dp[i] > dp[j] + 1 ? dp[i] : dp[j] + 1 + init: + dp[i] initally all = 1. (i = 0 ~ n). If no other number meets the requirement, at least it has itself. + Result: + dp[n - 1] + + Note: nums[j] <= nums[i] is the 'increasing' requirement + dp[j] + 1 means: best we can do at dp[j] + 1, is this better than what we already have on dp[i]? + +*/ + + +public class Solution { + /** + * @param nums: The integer array + * @return: The length of LIS (longest increasing subsequence) + */ + public int longestIncreasingSubsequence(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int n = nums.length; + int[] dp = new int[n]; + int max = 0; + for (int i = 0; i < n; i++) { + dp[i] = 1; + for (int j = 0; j < i; j++) { + if (nums[j] <= nums[i]){ + dp[i] = dp[i] > dp[j] + 1 ? dp[i] : dp[j] + 1; + } + } + if (dp[i] > max) { + max = dp[i]; + } + } + return max; + } +} + + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Palindromic Substring.java b/Others/old records/LintCode-Backup/Longest Palindromic Substring.java new file mode 100644 index 0000000..9093384 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Palindromic Substring.java @@ -0,0 +1,46 @@ +/* +Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. + +Example +Given the string = "abcdzdcab", return "cdzdc". + +Challenge +O(n2) time is acceptable. Can you do it in O(n) time. + +Tags Expand +String +*/ +/* + O(n) way, not done yet +*/ + + +/* + O(n^2) + Thoughts: + Like Palindrome Partioning II, try to use isPal[i][j] to verify each string (i,j). + If string(i,j) is valid, note down the (i,j) portion and find the longest. + This is a standard O(n^2) process +*/ +public class Solution { + /** + * @param s input string + * @return the longest palindromic substring + */ + public String longestPalindrome(String s) { + if (s == null || s.length() == 0) { + return s; + } + boolean isPal[][] = new boolean[s.length()][s.length()]; + String maxStr = ""; + for (int j = 0; j < s.length(); j++) { + for (int i = 0; i <= j; i++) { + if (s.charAt(i) == s.charAt(j) && (j - i <= 1 || isPal[i + 1][j - 1])) { + isPal[i][j] = true; + maxStr = maxStr.length() > s.substring(i, j + 1).length() ? maxStr : s.substring(i, j + 1); + } + } + }//end for j + return maxStr; + } +} diff --git a/Others/old records/LintCode-Backup/Longest Substring Without Repeating Characters.java b/Others/old records/LintCode-Backup/Longest Substring Without Repeating Characters.java new file mode 100755 index 0000000..bed8632 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Substring Without Repeating Characters.java @@ -0,0 +1,97 @@ +M + +方法1:只要有non-existing char就count++. 一旦有重复char: + i = 新出现重复Char的位置. + 重新init HashMap, count. + +这个方法每次都把map打碎重来, 是可以的,也没什么不好。就是在for里面改i,自己觉得不太顺.方法二可能顺一点。 + +方法2:用两个pointer, head和i. + head从index 0 开始。若没有重复char, 每次只有for loop的i++。每次取substring[head,i]作为最新的string. + 一旦有重复,那么意味着,从重复的老的那个index要往后加一格开始。所以head = map.get(i) +1. + +注意:head很可能被退回到很早的地方,比如abbbbbba,当遇到第二个a,head竟然变成了 head = 0+1 = 1. 当然这是不对的,所以head要确保一直增长,不回溯。 + + +``` +/* +Given a string, find the length of the longest substring without repeating characters. + +Example +For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. + +For "bbbbb" the longest substring is "b", with the length of 1. + +Challenge +O(n) time + +Tags Expand +String Two Pointers Hash Table +*/ + +/* + 02.02.2016 + Attempt2, Thoughts: + HashMap map + int head. + When char re-appear in map, 1. move head to repeating char's index + 1, 2. renew map with current index + + Note: head could repeat in earlier index, so make sure head does not travel back +*/ + +public class Solution { + public int lengthOfLongestSubstring(String s) { + if (s == null || s.length() == 0) { + return 0; + } + HashMap map = new HashMap(); + int head = 0; + int max = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (map.containsKey(c)) { + if (map.get(c) + 1 > head) { + head = map.get(c) + 1; + } + } + map.put(c, i); + String str = s.substring(head, i + 1); + max = Math.max(max, str.length()); + } + return max; + } +} + +/* +Attempt1, Thoughts: +Loop the string, HashSet to store the Character, count++, and use a max to store longest length. +Whenever a char exist in hashset, new hashset and count = 0, set i = 1st duplicate char, followed by i++, now start again. +*/ + +public class Solution { + public int lengthOfLongestSubstring(String s) { + if (s == null || s.length() == 0) { + return 0; + } + HashMap map = new HashMap(); + int count = 0; + int max = 0; + for (int i = 0; i < s.length(); i++) { + if (!map.containsKey(s.charAt(i))) { + map.put(s.charAt(i), i); + count++; + } else { + i = map.get(s.charAt(i)); + map = new HashMap(); + count = 0; + } + max = Math.max(max, count); + }//end for + + return max; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Substring with At Most K Distinct Characters.java b/Others/old records/LintCode-Backup/Longest Substring with At Most K Distinct Characters.java new file mode 100644 index 0000000..acce12d --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Substring with At Most K Distinct Characters.java @@ -0,0 +1,74 @@ +大清洗。 +map.size一旦超标,要把longest string最开头(marked by pointer:start)的那个char抹掉,而且要把它所有的appearance都抹掉;这样还不够,它最后一次出现以前的其他所有chars,也都要抹掉。 +大清洗的原因是: 一旦某一个char要被清除,由于substring必须是连续的,所以在它之前的所有chars都要被清洗。 +我去,黑帮大哥除龙头啊。 +简直就是要消灭伏地魔的7个魂器。 +``` +/* +Given a string s, find the length of the longest substring T that contains at most k distinct characters. + +Have you met this question in a real interview? Yes +Example +For example, Given s = "eceba", k = 3, + +T is "eceb" which its length is 4. + +Challenge +O(n), n is the size of the string s. + +Tags Expand +String Two Pointers LintCode Copyright Hash Table +*/ + +/* +Thoughts: +HashMap size cannot go over k. +Map. +Use a start pointer to track the begin of current longest substring. +If map.size() > k, then remove: count-= map.get(s.charAt(i)); map.remove(s.charAt(i)); + +Note: +assume we need to remove the first char of current longest string, and that char has multiple apperances later in the string +Do while on map.size>k, and remove all chars before the last appearce of that particular string. +Therefore, we need erase that particular char and all other chars before that particular char's last apperance. +*/ +public class Solution { + /** + * @param s : A string + * @return : The length of the longest substring + * that contains at most k distinct characters. + */ + public int lengthOfLongestSubstringKDistinct(String s, int k) { + if (s == null || s.length() == 0 || k <= 0) { + return 0; + } + HashMap map = new HashMap(); + int count = 0; + int start = 0; + int max = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (map.containsKey(c)) { + map.put(c, map.get(c) + 1); + } else { + map.put(c, 1); + while (map.size() > k) { + char rm = s.charAt(start); + int tempCount = map.get(rm); + if (tempCount > 1) { + map.put(rm, tempCount - 1); + } else { + map.remove(rm); + } + start++; + count--; + } + } + count++; + max = Math.max(max, count); + } + return max; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Longest Words.java b/Others/old records/LintCode-Backup/Longest Words.java new file mode 100644 index 0000000..d875ab6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Longest Words.java @@ -0,0 +1,71 @@ +/* +Given a dictionary, find all of the longest words in the dictionary. + +Example +Given + +{ + "dog", + "google", + "facebook", + "internationalization", + "blabla" +} +the longest words are(is) ["internationalization"]. + +Given + +{ + "like", + "love", + "hate", + "yes" +} +the longest words are ["like", "love", "hate"]. + +Challenge +It's easy to solve it in two passes, can you do it in one pass? + +Tags Expand +Enumeration String LintCode Copyright + +Thoughts: +Two pass: 1st, get longest length. 2nd pass, get all words. + +One pass: +1. Use hashmap: > +2. keep track of the longest length + +Review: +Map: put, get +ArrayList: add +We can get a value from map, and change directly on it, if that's an object (basically refer to the original object) +*/ + + +class Solution { + /** + * @param dictionary: an array of strings + * @return: an arraylist of strings + */ + ArrayList longestWords(String[] dictionary) { + if (dictionary == null || dictionary.length == 0) { + return null; + } + HashMap> map = new HashMap>(); + int longestLength = 0; + + for (int i = 0; i < dictionary.length; i++) { + int strLength = dictionary[i].length(); + if (map.containsKey(strLength)) { + map.get(strLength).add(dictionary[i]); + } else { + ArrayList list = new ArrayList(); + list.add(dictionary[i]); + map.put(strLength, list); + } + longestLength = strLength > longestLength ? strLength : longestLength; + } + return map.get(longestLength); + } +}; diff --git a/Others/old records/LintCode-Backup/Lowest Common Ancestor II.java b/Others/old records/LintCode-Backup/Lowest Common Ancestor II.java new file mode 100644 index 0000000..a497eff --- /dev/null +++ b/Others/old records/LintCode-Backup/Lowest Common Ancestor II.java @@ -0,0 +1,138 @@ +1. 曾经做的hashset的优化,找到的都存hashset. exist就return那个duplicate + + +2. 正常做法:2 lists +``` +/* +Lowest Common Ancestor II + +Given the root and two nodes in a Binary Tree. +Find the lowest common ancestor(LCA) of the two nodes. + +The lowest common ancestor is the node with largest depth which is the ancestor of both nodes. + +The node has an extra attribute parent which point to the father of itself. +The root's parent is null. + +Example +For the following binary tree: + + 4 + / \ +3 7 + / \ + 5 6 +LCA(3, 5) = 4 + +LCA(5, 6) = 7 + +LCA(6, 7) = 7 + +Tags Expand +LintCode Copyright Binary Tree +*/ + +/* + Thoughts: + 我之前的做法也是蛮彪悍的,HashSet只存所需要的parent, 其实算是一个优化,更节省空间。 + 12.11.2015. + 今天这个再来实现一个普通的做法,存在两个list里面。有parent的题目本身比没parent更简单。 + 从头遍历两个list. + 1. 一旦分叉,分叉口的parent就是要找的。 + 2. 如果两个list一直相等,那他们就是同一个node + + border case: if both null, just return null. + if only 1 is null, let one of the node be ancestor; since null can be anywhere. +*/ + +public class Solution { + /** + * @param root: The root of the tree + * @param A, B: Two node in the tree + * @return: The lowest common ancestor of A and B + */ + public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, + ParentTreeNode A,ParentTreeNode B) { + if (root == null || (A == null && B == null)) { + return null; + } else if (A == null || B == null) { + return A == null ? B : A; + } + //Populate listA, listB + ArrayList listA = new ArrayList(); + ArrayList listB = new ArrayList(); + + while (A != root) { + listA.add(0, A); + A = A.parent; + } + listA.add(0, A); + while (B != root) { + listB.add(0, B); + B = B.parent; + } + listB.add(0, B); + + int size = listA.size() > listB.size() ? listB.size() : listA.size(); + + for (int i = 0; i < size; i++) { + if (listA.get(i) != listB.get(i)) { + return listA.get(i).parent; + } + } + + return listA.get(size - 1); + } +} + + +/* + Thoughts: + Try to get upper-level parent, store in hashMap. + First time when the node duplicate in map, that will be the first common parent. +*/ + +/** + * Definition of ParentTreeNode: + * + * class ParentTreeNode { + * public ParentTreeNode parent, left, right; + * } + */ +public class Solution { + /** + * @param root: The root of the tree + * @param A, B: Two node in the tree + * @return: The lowest common ancestor of A and B + */ + public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, + ParentTreeNode A, + ParentTreeNode B) { + if (root == null || (A == null && B == null)) { + return null; + } else if (A == null || B == null) { + return A == null ? B : A; + } + + HashSet set = new HashSet(); + while (A != null || B != null) { + if (A != null) { + if (set.contains(A)) { + return A; + } + set.add(A); + A = A.parent; + } + if (B != null) { + if (set.contains(B)) { + return B; + } + set.add(B); + B = B.parent; + } + } + return root; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Lowest Common Ancestor.java b/Others/old records/LintCode-Backup/Lowest Common Ancestor.java new file mode 100644 index 0000000..b8ebf5b --- /dev/null +++ b/Others/old records/LintCode-Backup/Lowest Common Ancestor.java @@ -0,0 +1,199 @@ +E + +方法1:O(n) space O(h) time。把两条线binary search出来。找第一个不同的parent. 代码长。 Iterative + +方法2:O(1) sapce O(h). Recursive. 循环的截点是: +当root == null或者 A B 任何一个在findLCA底部被找到了(root== A || root == B),那么就return 这个root. + +三种情况: +1. A,B都找到,那么这个level的node就是其中一层的parent。其实,最先recursively return到的那个,就是最底的LCA parent. +2. A 或者 B 找到,那就还没有公共parent,return 非null得那个。 +3. A B 都null, 那就找错了没有呗, return null + + +``` + +/* +33% Accepted +Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes. + +The lowest common ancestor is the node with largest depth which is the ancestor of both nodes. + +Example + 4 + + / \ + + 3 7 + + / \ + + 5 6 + +For 3 and 5, the LCA is 4. + +For 5 and 6, the LCA is 7. + +For 6 and 7, the LCA is 7. + +Tags Expand +Binary Tree LintCode Copyright + + +*/ + +/* + Thoughts: + Revisit this on 12.11.2015. + To correctly understand this approach when there is not 'parent' atribute available in node. + + We divide and coquer (in this case DFS) into 2 branches, and we are actually asking each node to check: + Do I have a leaf child of nodeA (could be futher down in the tree)? + Do I have a leaf child of nodeB (could be futher down in the tree)? + 1. If I have leaf child of A && B, then i'm the deepest parent in line! Return. + 2. If I only have A, or B: mark myself as an ancestor of A or B. + 3. If I don't have leaf child of A nor B, I'm not an ancestor, failed, return null. + + After the common ancestor is found at any deep level, and returned itself to parent level, + we can assume other branches must be null (because they are not ancestor, since we are), + then the this common ancestor node will be passed to highest level. + + However, with one problem: + When review the problem, calling the recursive functions of the 'lowestCommonAncestor' is just + confusing. It's not easy to see the relationship between leef child and ancestor candidates. + + +*/ +public class Solution { + /** + * @param root: The root of the binary search tree. + * @param A and B: two nodes in a Binary. + * @return: Return the least common ancestor(LCA) of the two nodes. + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { + if (root == null || root == A || root == B) { + return root; + } + TreeNode left = lowestCommonAncestor(root.left, A, B); + TreeNode right = lowestCommonAncestor(root.right, A, B); + + if (left != null && right != null) {//Found both A leaf and B leaf + return root; + } else if (left != null || right != null) { + return left != null ? left : right; + } else { + return null; + } + } +} + +/* +//Another way using regular way: see solution: +This is for the case that each node can reach its higher level parent.... +Basically put all parents into a list, +[root, next level, next level... parent, nodeA] +[root, next level, next level... parent, nodeB] +compare these 2 lists see when to have a different node. that node.parent is the parent + +Or, if the list is identical, then their parent might just be same right-above-level parent. + +http://www.ninechapter.com/solutions/lowest-common-ancestor/ +*/ + + +/* +Older same version +Think process: +Divide and conquer: +start from root, divide into 2 ways … +At the bottom, if it’s node1 or node2, send back. +1. If any line that’s not having node1 or node2 as leaf, they will become null. +2. At the ancestor spot: because node1!=null and node2!=null, the ancestor return itself. +3. From this point, any level higher, it will return the ancestor because the other child-line has been null at the time. +When it returns to the top, return solution : ancestor + +*/ +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: The root of the binary search tree. + * @param A and B: two nodes in a Binary. + * @return: Return the least common ancestor(LCA) of the two nodes. + */ + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { + if (root == null || root == A || root == B) { + return root; + } + TreeNode left = lowestCommonAncestor(root.left, A, B); + TreeNode right = lowestCommonAncestor(root.right, A, B); + + if (left == null && right == null) { + return null; + } else if (left == null) { + return right; + } else if (right == null) { + return left; + } else { + return root; + } + } +} + + +//Extra storage, not a good method: + + //Find two lists of nodes + //First non-common's previous one from two lists, or the end of one list, is the LCA +public class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || p == null || q == null) { + return root; + } + ArrayList list1 = new ArrayList(); + ArrayList list2 = new ArrayList(); + TreeNode node = root; + list1.add(node); + while (node.val != p.val) { + if (p.val < node.val) { + node = node.left; + } else { + node = node.right; + } + list1.add(node); + } + node = root; + list2.add(node); + while (node.val != q.val) { + if (q.val < node.val) { + node = node.left; + } else { + node = node.right; + } + list2.add(node); + } + + int size = list1.size() < list2.size() ? list1.size() : list2.size(); + node = root; + for (int i = 0; i < size; i++) { + if (list1.get(i) != list2.get(i)) { + break; + } + node = list1.get(i); + } + + return node; + } +} + + +``` diff --git a/Others/old records/LintCode-Backup/Majority Number II.java b/Others/old records/LintCode-Backup/Majority Number II.java new file mode 100644 index 0000000..91b1d96 --- /dev/null +++ b/Others/old records/LintCode-Backup/Majority Number II.java @@ -0,0 +1,83 @@ +/* +Given an array of integers, the majority number is the number that occurs more than 1/3 of the size of the array. + +Find it. + +Note +There is only one majority number in the array + +Example +For [1, 2, 1, 2, 1, 3, 3] return 1 + +Challenge +O(n) time and O(1) space + +Thinking process: +Need to think the relations of 3 parts of the array: +1. Assume a > 1/3, which is the candidate were are looking for + However, only konwing a appears more than 1/3 of the array, does not mean there is no other element appears more than 1/3, for example, aaaaabcccccc, a = 5/12, b = 6/12. The majority is b. +2. Consider another element b, which is a different element rather than a. Discuss the 2 conditions of b. +3. Consider the rest of the array is in set c, which can contain all different elements. + +Discuss relations between a, b, c +Assume a > 1/3 +Case1: b < 1/3 + given: a > 1/3, means b + c < 2/3, known b < 1/3 + get: c < 1/3 + conclusion: a is the majority +Case2: b > 1/3 + given: a + b ? 2/3 + get: c < 1/3 + conclusion: return the greater element# of a or b + +Implementation: +1. Have valA and valB two pointers to represent a and between +2. Check valA against the array to count duplicates, similar as in Majority Number I +3. Check valB against ..... +4. Note: at each index i, only one of valA or valB is checked. That means, we evaluate a and b individually against the section c. +5. At the end, we found 2 candidates: a and b. Now compare the # of a and b to see which is greater. +*/ + +public class Solution { + /** + * @param nums: A list of integers + * @return: The majority number that occurs more than 1/3 + */ + public int majorityNumber(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return -1; + } + int valA = 0; + int valB = 0; + int countA = 0; + int countB = 0; + for (int i = 0; i < nums.size(); i++) { + if (countA == 0 || nums.get(i) == valA) { + valA = nums.get(i); + countA++; + } else if (countB == 0 || nums.get(i) == valB) { + valB = nums.get(i); + countB++; + } else {//None of a || b matches + countA--; + countB--; + if (countA == 0) { + countA = 1; + valA = nums.get(i); + } else if (countB == 0) { + countB = 1; + valB = nums.get(i); + } + } + }//For + + countA = 0; + countB = 0; + for (int num : nums) { + countA += num == valA ? 1 : 0; + countB += num == valB ? 1 : 0; + } + return countA > countB ? valA : valB; + } +} + diff --git a/Others/old records/LintCode-Backup/Majority Number III.java b/Others/old records/LintCode-Backup/Majority Number III.java new file mode 100644 index 0000000..70f58d0 --- /dev/null +++ b/Others/old records/LintCode-Backup/Majority Number III.java @@ -0,0 +1,65 @@ +/* +Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array. Find it. + +Note +There is only one majority number in the array. + +Example +For [3,1,2,3,2,3,3,4,4,4] and k = 3, return 3 + +Challenge +O(n) time and O(k) extra space + +Thinking process: +Very similar to Majority I, II, except we can use a HashMap to store information (value, count). +Having a HashMap we have one advantage: when checking if current value matches any previously recorded val, just do a map.containsKey(val). +When a pair in hashMap has count ==0, remove this pair. +Note, to learn how to use iterator in HashMap. +Note: when map.containsKey(currVal) == false, the code checks map.size() == k before count-- perations. This is because: +We first need to put k candidates into HashMap before we count-- from all of them. If map.size() < k, that means we still have free spot for candidate in the HashMap, so in this case we do: map.put(candidateKey, 1). +*/ + + +public class Solution { + /** + * @param nums: A list of integers + * @param k: As described + * @return: The majority number + */ + public int majorityNumber(ArrayList nums, int k) { + if (nums == null || nums.size() == 0) { + return -1; + } + HashMap map = new HashMap(); + for (Integer num : nums) { + if (map.containsKey(num)) {//Found duplicates, count++ + map.put(num, map.get(num) + 1); + } else { + if (map.size() == k) {//All candidates added, do count-- + Iterator> iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + if (entry.getValue() - 1 == 0) { + iter.remove(); + } else { + map.put(entry.getKey(), entry.getValue() - 1); + } + }//While + } else { + map.put(num, 1); + } + } + }//For + + int result = 0; + int max = 0; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() > max) { + max = entry.getValue(); + result = entry.getKey(); + } + } + return result; + } +} + diff --git a/Others/old records/LintCode-Backup/Majority Number.java b/Others/old records/LintCode-Backup/Majority Number.java new file mode 100644 index 0000000..600d71f --- /dev/null +++ b/Others/old records/LintCode-Backup/Majority Number.java @@ -0,0 +1,45 @@ +/* +Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it. + +Example +For [1, 1, 1, 1, 2, 2, 2], return 1 + +Challenge +O(n) time and O(1) space + +Tag: Enumeration + +Thinking process: +Natural thinking process: count how many you have for 1st element, if next one is the same, count++, if next one is not the same, count- -. +When count ==0, that means other types of element has same amount as the 1st majority number, they are even. +From this point, count the value at current position as the majority number, keep the loop rolling. +Note: this solutions works only when the given array has a valid solution. +CounterCase:[111223], with actually return 3 as the majority number. But again, this is not a valid input in this case. +*/ + +public class Solution { + /** + * @param nums: a list of integers + * @return: find a majority number + */ + public int majorityNumber(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return -1; + } + int majorNum = nums.get(0); + int count = 1; + for (int i = 1; i < nums.size(); i++) { + if (majorNum == nums.get(i)) { + count++; + } else { + count--; + } + if (count == 0) { + majorNum = nums.get(i); + count = 1; + } + } + return majorNum; + } +} + diff --git a/Others/old records/LintCode-Backup/Matrix Zigzag Traversal.java b/Others/old records/LintCode-Backup/Matrix Zigzag Traversal.java new file mode 100644 index 0000000..629772f --- /dev/null +++ b/Others/old records/LintCode-Backup/Matrix Zigzag Traversal.java @@ -0,0 +1,75 @@ +分析4个step. +小心走位。 +``` +/* +Matrix Zigzag Traversal + +Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in ZigZag-order. + +Example +Given a matrix: + +[ + [1, 2, 3, 4], + [5, 6, 7, 8], + [9,10, 11, 12] +] +return [1, 2, 5, 9, 6, 3, 4, 7, 10, 11, 8, 12] + +Tags Expand +LintCode Copyright Matrix +*/ + +/* + Always have the 4 states: right 1 step, left-bottom corner, right 1 step, up-right-corner. + If any of the 4 steps can't proceed because of hitting the wall, just go down 1 step. + +*/ + +public class Solution { + /** + * @param matrix: a matrix of integers + * @return: an array of integers + */ + public int[] printZMatrix(int[][] matrix) { + int[] rst = null; + if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { + return rst; + } + int n = matrix.length; + int m = matrix[0].length; + rst = new int[n * m]; + if (matrix.length == 1) { + return matrix[0]; + } + int i = 0, j = 0; + int ind = 0; + rst[ind] = matrix[i][j]; + ind++; + while (ind < rst.length) { + //Right 1 step, or down + if (j + 1 < m || i + 1 < n) { + if (j + 1 < m) j++; + else if (i + 1 < n) i++; + rst[ind++] = matrix[i][j]; + } + //Move left-bottom: + while (j - 1 >= 0 && i + 1 < n) { + rst[ind++] = matrix[++i][--j]; + } + //Move down, or right + if (j + 1 < m || i + 1 < n) { + if (i + 1 < n) i++; + else if (j + 1 < m) j++; + rst[ind++] = matrix[i][j]; + } + //Move right-up: + while (j + 1 < m && i - 1 >= 0) { + rst[ind++] = matrix[--i][++j]; + } + }//end while + return rst; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Max Tree.java b/Others/old records/LintCode-Backup/Max Tree.java new file mode 100644 index 0000000..693fa14 --- /dev/null +++ b/Others/old records/LintCode-Backup/Max Tree.java @@ -0,0 +1,105 @@ +MaxTree值得记。 +Stack从下到上,最大在下。维持和利用这个性质: +把所有小于curr node的,全Pop出来,最后一个小于Curr的,放在curr.left. +接下去stack里面的一定是大于curr,那就变成curr的left parent. +结尾:stack底部一定是最大的那个,也就是max tree的头。 + +妙啊!!! +``` +/* +Given an integer array with no duplicates. A max tree building on this array is defined as follow: + +The root is the maximum number in the array +The left subtree and right subtree are the max trees of the subarray divided by the root number. +Construct the max tree by the given array. + +Have you met this question in a real interview? Yes +Example +Given [2, 5, 6, 0, 3, 1], the max tree constructed by this array is: + + 6 + / \ + 5 3 + / / \ +2 0 1 +Challenge +O(n) time and memory. + +Tags Expand +LintCode Copyright Stack Cartesian Tree +*/ + +/* +Can't fingure express tree, so look at Max Tree problem first +Good explain here:http://blog.welkinlan.com/2015/06/29/max-tree-lintcode-java/ + +Iterate from left of array to right. So, every element we take, it will be the current right-most element. +Goal: find left-child, and find its left-parent. +Do for loop on all nodes.Remember to push the stack on every for iteration. +1. Left-child: use while loop to find the very last smaller node(comparing with curr Node), and set that as left-child. +2. Then, of course, the node left in stack (if still existing a node), will be the first larger node. That, will become curr + node's left parent. +3. At the end, we need to return largest element, which is root. Just by poping off all nodes will give us the bottom-largest-node + +Note: Interesting behavior: +Stack: always stores the largest value at bottom. In above example, when 6 gets in stack, it will never come back. +All smaller element (smaller than current point) will be poped out, +and of course, the last-possible-smaller element will be the largest smaller point on stack, then we attach it to current node. + +These behavior keeps larger value on upper level of the tree + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +/* + +Given [2, 5, 6, 0, 3, 1], the max tree constructed by this array is: + + 6 + / \ + 5 3 + / / \ +2 0 1 +Challenge + +*/ +public class Solution { + /** + * @param A: Given an integer array with no duplicates. + * @return: The root of max tree. + */ + public TreeNode maxTree(int[] A) { + if (A == null || A.length == 0) { + return null; + } + Stack stack = new Stack(); + for (int i = 0; i < A.length; i++) { + TreeNode node = new TreeNode(A[i]); + while (!stack.isEmpty() && node.val >= stack.peek().val) { + node.left = stack.pop(); + } + if (!stack.isEmpty()) { + stack.peek().right = node; + } + stack.push(node); + } + + TreeNode rst = stack.pop(); + while(!stack.isEmpty()) { + rst = stack.pop(); + } + return rst; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Maximal Square.java b/Others/old records/LintCode-Backup/Maximal Square.java new file mode 100644 index 0000000..fd858f9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Maximal Square.java @@ -0,0 +1,79 @@ +M + +DP问题 + +从边长为2的正方形看起,看左上角的那个点。 +如何确定是个正方形?首先看左上点是不是1,然后看右边,右下,下面的点是不是1. + +DP就是根据这个特征想出来。dp[i,j]: 从右下往左上推算,包括当前点在内的所能找到的最大边长。 + 注意dp[i,j]被右边,右下,下面三点的最短点所限制。这就是fn. + +Init: + 把右边,下边两个边缘init一遍,存matrix在这两条边上的值,代表的意思也就是dp[i][j]在这些点上的初始值:变成为1 or 0. + +``` +/* +Given a 2D binary matrix filled with 0's and 1's, +find the largest square containing all 1's and return its area. + +Example +For example, given the following matrix: + +1 0 1 0 0 +1 0 1 1 1 +1 1 1 1 1 +1 0 0 1 0 +Return 4. + +Tags Expand +Dynamic Programming +*/ + +/* + Thoughts: Seem that we need to check on right and bottom spots for 2x2 1's. + If all size spots are clean, len++, square = newLen ^ 2. + DP[i,j]: the longest square lengh that this matrix[i][j] reach. + dp[i,j] = Math.min(dp[i][j+1], dp[i+1][j], dp[i+1][j+1]) + init: + dp[n-1][0 ~ m-1] = matrix[n-1][0 ~ m-1] == 0 ? 0 : 1; + dp[0 ~ n-1][m-1] = matrix[0 ~ n-1][m-1] == 0 ? 0 : 1; + for from rigt-bottom conor. + Maintain a max area +*/ + +public class Solution { + /** + * @param matrix: a matrix of 0 and 1 + * @return: an integer + */ + public int maxSquare(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return 0; + } + int n = matrix.length; + int m = matrix[0].length; + int[][] dp = new int[n][m]; + int maxLen = 0; + //Init + for (int i = 0; i < m; i++) { + dp[n - 1][i] = matrix[n - 1][i]; + maxLen = Math.max(maxLen, dp[n - 1][i]); + } + for (int i = 0; i < n; i++) { + dp[i][m - 1] = matrix[i][m - 1]; + maxLen = Math.max(maxLen, dp[i][m - 1]); + } + //function + for (int i = n - 2; i >= 0; i--) { + for (int j = m - 2; j >= 0; j--) { + if (matrix[i][j] == 1) { + dp[i][j] = Math.min(Math.min(dp[i][j + 1], dp[i + 1][j]), dp[i + 1][j + 1]) + 1; + maxLen = Math.max(maxLen, dp[i][j]); + } + } + } + return maxLen * maxLen; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Maximum Depth of Binary Tree.java b/Others/old records/LintCode-Backup/Maximum Depth of Binary Tree.java new file mode 100644 index 0000000..6e01816 --- /dev/null +++ b/Others/old records/LintCode-Backup/Maximum Depth of Binary Tree.java @@ -0,0 +1,63 @@ +DFS +Divide and conquer +``` +/* +71% Accepted +Given a binary tree, find its maximum depth. + +The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. + +Example +Given a binary tree as follow: + + 1 + + / \ + + 2 3 + + / \ + + 4 5 + +The maximum depth is 3 + +Tags Expand +Tree Binary Tree Depth First Search + +Thinking process: +check if root is null, return 0 if so. +Divide and return integer as the depth +Conquer: find the max and return depth + 1. +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: An integer. + */ + public int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + int left = maxDepth(root.left); + int right = maxDepth(root.right); + + return Math.max(left, right) + 1; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Maximum Product Subarray.java b/Others/old records/LintCode-Backup/Maximum Product Subarray.java new file mode 100644 index 0000000..7f2409d --- /dev/null +++ b/Others/old records/LintCode-Backup/Maximum Product Subarray.java @@ -0,0 +1,104 @@ +/* +Find the contiguous subarray within an array (containing at least one number) which has the largest product. + +Example +For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6. + +Tags Expand +Dynamic Programming Subarray +*/ +/* +Attempt2: Use a max array and a min array. (http://www.jiuzhang.com/solutions/maximum-product-subarray/) +This is similar to my original attempt1, but saves a lot memory space. + +0. Max array is always positive, Min array is always negative. Use these 2 arrays to keep track of largest positive number and smallest negative number +1. When current nums[i] > 0, use max[i - 1] * nums[i]. +2. When current nums[i] < 0, user min[i - 1] * nums[i]; +3. Don't for get to calculate both max and min for each i, for next iteration to use. + +In either case, we will produce largest possible product. + +Trick: depending on nums[i] is positive or negative, calculate differently ... +*/ + +public class Solution { + public int maxProduct(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int[] max = new int[nums.length]; + int[] min = new int[nums.length]; + max[0] = nums[0]; + min[0] = nums[0]; + int rst = max[0]; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > 0) { + max[i] = Math.max(nums[i], max[i - 1] * nums[i]);//the nums[i] could just be the best option + min[i] = Math.min(nums[i], min[i - 1] * nums[i]); + } else { + max[i] = Math.max(nums[i], min[i - 1] * nums[i]); + min[i] = Math.min(nums[i], max[i - 1] * nums[i]); + } + rst = Math.max(rst, max[i]); + } + return rst; + } +} + + + +/* +Attempt1 thoughts: +97% correct. However, this exceeds memory, basically the DP[][] is too large. +Draw a 2D array: +Row: Start from a number ROW[i], what contiguous value can we get: + 0 1 2 3 + ------------- + 2 3 -2 4 +0| 2 2 6 -12 -48 +1| 3 x x -6 -24 +2| -2 x x x -8 +3| 4 x x x x + +Look, according to the rules of (contiguous subarray), we can't do Row[i]xRow[i], so we have to do: Row[i]xROW[i+1]xROW[i+2]...etc +Goal: find the max in DP +1. Define DP[0][0] = nums[0]; +2. DP[i][j] = DP[i][j - 1] * nums[j] +3. And we keep track of the max value + +Note: j will always > i, so cases that i >= j are not necessary. +*/ + + +public class Solution { + /** + * @param nums: an array of integers + * @return: an integer + */ + public int maxProduct(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int[][] DP = new int[nums.length][nums.length]; + DP[0][0] = nums[0]; + int max = DP[0][0]; + + for (int i = 0; i < nums.length; i++) { + for (int j = 1; j < nums.length; j++) { + if (i == j) { + DP[i][j] = nums[j]; + } + if (j > i) { + if (DP[i][j - 1] == 0) { + DP[i][j] = nums[j]; + } else { + DP[i][j] = DP[i][j - 1] * nums[j]; + } + max = Math.max(max, DP[i][j]); + } + max = Math.max(max, nums[j]); + } + } + return max; + } +} \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Maximum Subarray III.java b/Others/old records/LintCode-Backup/Maximum Subarray III.java new file mode 100644 index 0000000..941e74b --- /dev/null +++ b/Others/old records/LintCode-Backup/Maximum Subarray III.java @@ -0,0 +1,33 @@ +/* + +Given an array of integers and a number k, find k non-overlapping subarrays which have the largest sum. + +The number in each subarray should be contiguous. + +Return the largest sum. + +Have you met this question in a real interview? Yes +Example +Given [-1,4,-2,3,-2,3], k=2, return 8 + +Note +The subarray should contain at least one number + +Tags Expand +LintCode Copyright Dynamic Programming Subarray Array +*/ + +/* + NOT DONE +*/ +public class Solution { + /** + * @param nums: A list of integers + * @param k: An integer denote to find k non-overlapping subarrays + * @return: An integer denote the sum of max k non-overlapping subarrays + */ + public int maxSubArray(ArrayList nums, int k) { + // write your code + } +} + diff --git a/Others/old records/LintCode-Backup/MaximumSubarray.java b/Others/old records/LintCode-Backup/MaximumSubarray.java new file mode 100644 index 0000000..462c0a8 --- /dev/null +++ b/Others/old records/LintCode-Backup/MaximumSubarray.java @@ -0,0 +1,154 @@ +想着用一用prefix sum. 把值一个个叠加。 +然后presum[j] - presum[i- 1] 就是 (i,j)之间的和。 +``` +/* +Maximum Subarray Show Result My Submissions + +35% Accepted +Given an array of integers, find a contiguous subarray which has the largest sum. + +Note +The subarray should contain at least one number + +Example +For example, given the array [−2,2,−3,4,−1,2,1,−5,3], the contiguous subarray [4,−1,2,1] has the largest sum = 6. + +Challenge +Can you do it in time complexity O(n)? + +Tags Expand +Array SubArray Greedy Enumeration LintCode Copyright + + +*/ + + + +/* + + Thinking proces: + Store the sum in a array. + Normally, sum[i] = sum[i - 1] + nums[i]. + However, if sum[i - 1] is a nagetive number, that means sum[i - 1] won't do any good for later sum but only decrease the sum. + In this case, when sums[i - 1] < 0, we don't add it. + + When sum[i-1], it actaully starts from nums.get(i) again. +*/ + +public class Solution { + /** + * @param nums: A list of integers + * @return: A integer indicate the sum of max subarray + */ + public int maxSubArray(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + int[] sums = new int[nums.size()]; + sums[0] = nums.get(0); + int maxSum = sums[0]; + for (int i = 1; i < sums.length; i++) { + if (sums[i - 1] < 0) { + sums[i] = nums.get(i); + } else { + sums[i] = sums[i - 1] + nums.get(i); + } + maxSum = Math.max(maxSum, sums[i]); + } + return maxSum; + } +} + +/* + Thoughts: 11.23.2015 + Originally, the method is:When sum[i-1], it actaully starts from nums.get(i) again. + Calculate the max + New way of using preSum. + sum[i ~ j] = preSum[j] - preSum[i - 1]; + Calculate the max + + Though this helps further problems, but it's actaully O(n^2) +*/ + + +public class Solution { + /** + * @param nums: A list of integers + * @return: A integer indicate the sum of max subarray + */ + public int maxSubArray(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + + int n = nums.length; + int[] preSum = new int[n]; + preSum[0] = nums[0]; + int max = Math.max(Integer.MIN_VALUE, preSum[0]); + for (int i = 1; i < n; i++) { + preSum[i] = preSum[i - 1] + nums[i]; + } + for (int j = n - 1; j > 0; j--) { + for (int i = 0; i <= j; i++) { + int sum = 0; + if (i == 0) { + sum = preSum[j]; + } else { + sum = preSum[j] - preSum[i - 1]; + } + max = Math.max(sum, max); + } + }//end for + return max; + } +} + + + +/* + To further extend the prefix sum idea, we are really trying: + Use regular preSum - smallest preSum in earlier spots, which gives largest value. + So maintain a regular preSum, and maintain a minPreSum. + Maintain a max to mark the difference between (preSum - minPreSum) + Also, here, we dont' really care about index.So just skip index. + O(n) here +*/ + +public class Solution { + /** + * @param nums: A list of integers + * @return: A integer indicate the sum of max subarray + */ + public int maxSubArray(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int preSum = 0; + int minPreSum = 0; + int max = Integer.MIN_VALUE; + for (int i = 0; i < nums.length; i++) { + preSum += nums[i]; + max = Math.max(max, preSum - minPreSum); + minPreSum = Math.min(minPreSum, preSum); + } + return max; + } +} + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/MaximumSubarrayII.java b/Others/old records/LintCode-Backup/MaximumSubarrayII.java new file mode 100644 index 0000000..7e0c27c --- /dev/null +++ b/Others/old records/LintCode-Backup/MaximumSubarrayII.java @@ -0,0 +1,150 @@ +新的解法还是用到了prefix sum. +注意:右边算prefix sum, 看上去好像是什么postfix sum? 其实不是。其实都和prefix一样。 +我们需要的那部分prefix sum,其实就是一段数字的总和。 +所以从右边累计上来的。也是一样可以的。 +``` +/* +Given an array of integers, find two non-overlapping subarrays which have the largest sum. + +The number in each subarray should be contiguous. + +Return the largest sum. + +Note +The subarray should contain at least one number + +Example +For given [1, 3, -1, 2, -1, 2], the two subarrays are [1, 3] and [2, -1, 2] or [1, 3, -1, 2] and [2], they both have the largest sum 7. + +Challenge +Can you do it in time complexity O(n) ? + +Tags Expand +Greedy Enumeration Array LintCode Copyright SubArray Forward-Backward Traversal + +*/ +/* + Thoughts: 11.23.2015 + Similar to Maximum Subarray。 Now just try to build 2 maximum subbary, from left/right. + Meetpoint i, will give largest possible sum +*/ +public class Solution { + /** + * @param nums: A list of integers + * @return: An integer denotes the sum of max two non-overlapping subarrays + */ + public int maxTwoSubArrays(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + + int preSum = 0; + int minPreSum = 0; + int max = Integer.MIN_VALUE; + int n = nums.size(); + int[] left = new int[n]; + int[] right = new int[n]; + for (int i = 0; i < n; i++) { + preSum += nums.get(i); + max = Math.max(max, preSum - minPreSum); + minPreSum = Math.min(minPreSum, preSum); + left[i] = max; + } + preSum = 0; + minPreSum = 0; + max = Integer.MIN_VALUE; + for (int i = n - 1; i >= 0; i--) { + preSum += nums.get(i); + max = Math.max(max, preSum - minPreSum); + minPreSum = Math.min(minPreSum, preSum); + right[i] = max; + } + max = Integer.MIN_VALUE; + for (int i = 0; i < n - 1; i++) { + int rst = left[i] + right[i + 1]; + max = Math.max(max, rst); + } + + return max; + } +} + + + + + +/* + +Thinking process: +Find frontSum: largest sum from index 0 till current at each index. +Find endSum: largest sum from end(endSum.length - 1) to current at each index. +Add them up: at any point i, leftSum + rightSum = largest 2 non-overlap sum. + i + i i + i i +i i + +*/ +public class Solution { + /** + * @param nums: A list of integers + * @return: An integer denotes the sum of max two non-overlapping subarrays + */ + public int maxTwoSubArrays(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + int[] frontSum = new int[nums.size()]; + int[] endSum = new int[nums.size()]; + int maxSum = 0; + frontSum[0] = nums.get(0); + //Init frontSum + for (int i = 1; i < frontSum.length; i++) { + if (frontSum[i - 1] < 0) { + frontSum[i] = nums.get(i); + } else { + frontSum[i] = frontSum[i - 1] + nums.get(i); + } + } + maxSum = frontSum[0]; + //Find max + for (int i = 1; i < frontSum.length; i++) { + if (frontSum[i] < maxSum) { + frontSum[i] = maxSum; + } else { + maxSum = frontSum[i]; + } + } + + //Init endSum + endSum[endSum.length - 1] = nums.get(nums.size() - 1); + for (int i = endSum.length - 2; i >= 0; i--) { + if (endSum[i + 1] < 0) { + endSum[i] = nums.get(i); + } else { + endSum[i] = endSum[i + 1] + nums.get(i); + } + } + //Find max + maxSum = endSum[endSum.length - 1]; + for (int i = endSum.length - 2; i >= 0; i--) { + if (endSum[i] < maxSum) { + endSum[i] = maxSum; + } else { + maxSum = endSum[i]; + } + } + //Calculate max Sum + maxSum = Integer.MIN_VALUE; + for (int i = 0; i < nums.size() - 1; i++) { + maxSum = Math.max(maxSum, frontSum[i] + endSum[i + 1]); + } + return maxSum; + } +} + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Median of two Sorted Arrays.java b/Others/old records/LintCode-Backup/Median of two Sorted Arrays.java new file mode 100644 index 0000000..09b843f --- /dev/null +++ b/Others/old records/LintCode-Backup/Median of two Sorted Arrays.java @@ -0,0 +1,39 @@ +/* + +Median of two Sorted Arrays + +There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. + +Example +Given A=[1,2,3,4,5,6] and B=[2,3,4,5], the median is 3.5. + +Given A=[1,2,3] and B=[4,5], the median is 3. + +Challenge +The overall run time complexity should be O(log (m+n)). + +Tags Expand +Sorted Array Divide and Conquer Array Zenefits Uber Google + +*/ + +/* + Thoughts: + Trivial: merge and find median. NOPE: have to be in log(m+n) time + http://www.jiuzhang.com/solutions/median-of-two-sorted-arrays/ + + http://fisherlei.blogspot.com/2012/12/leetcode-median-of-two-sorted-arrays.html + +*/ + +class Solution { + /** + * @param A: An integer array. + * @param B: An integer array. + * @return: a double whose format is *.5 or *.0 + */ + public double findMedianSortedArrays(int[] A, int[] B) { + // write your code here + } +} + diff --git a/Others/old records/LintCode-Backup/Median.java b/Others/old records/LintCode-Backup/Median.java new file mode 100644 index 0000000..2dac899 --- /dev/null +++ b/Others/old records/LintCode-Backup/Median.java @@ -0,0 +1,107 @@ +/* +Given a unsorted array with integers, find the median of it. + +A median is the middle number of the array after it is sorted. + +If there are even numbers in the array, return the N/2-th number after sorted. + +Example +Given [4, 5, 1, 2, 3], return 3 + +Given [7, 9, 4, 5], return 5 + +Challenge +O(n) time. + +Tags Expand +LintCode Copyright Quick Sort Array + + +*/ +/* + Recap 12.09.2015. + O(n) means just run through it. It's similar to Partition array: it tries to split the list into 2 parts, and find the pivot. +*/ + +/* +Thoughts: +Use standard quick sort, but the goal is to look for the middle point. +1. Get middle point: remember to -1 because we are looking for position, rather than length. +2. Increase low pointer until find a point >= piviot +3. Decrease high pointer until find a point < poviot +4. Swap the low and high: this set the first value greather than pivot to the right, and first avlue less than pivot to the left. +5. after low and high pointer meets, swap low with the piviot: simply because pivot should be the break point of low and high +6. at the end, the low sould be the middle point, which is the point we are looking for. return corresponding recursive helper. + +*/ +public class Solution { + /** + * @param nums: A list of integers. + * @return: An integer denotes the middle number of the array. + */ + public int median(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + if (nums.length % 2 == 0) { + return helper(nums, 0, nums.length - 1, nums.length/2 - 1); + } else { + return helper(nums, 0, nums.length - 1, nums.length/2); + } + } + + public void swap(int[] nums, int x, int y){ + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } + + public int helper(int[] nums, int start, int end, int mid) { + int pivot = end; + int num = nums[pivot]; + int low = start; + int high = end; + while (low < high) { + while(low < high && nums[low] < num) { + low++; + } + while(low < high && nums[high] >= num) { + high--; + } + swap(nums, low, high); + } + swap(nums, low, pivot); + if (low == mid) { + return nums[low]; + } else if (low < mid) { + return helper(nums, low + 1, end, mid); + } else { + return helper(nums, start, low - 1, mid); + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Merge Intervals.java b/Others/old records/LintCode-Backup/Merge Intervals.java new file mode 100644 index 0000000..518bf89 --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge Intervals.java @@ -0,0 +1,73 @@ +/* + +Given a collection of intervals, merge all overlapping intervals. + +Example +Given intervals => merged intervals: + +[ [ + [1, 3], [1, 6], + [2, 6], => [8, 10], + [8, 10], [15, 18] + [15, 18] ] +] +Challenge +O(n log n) time and O(1) extra space. + +Tags Expand +Sort Array + +Thoughts: +1. use comparator to sort list. Well, no need to create a new class. Just do it inline. +2. iterate through the list and merge (whenever there is overlap) + + +Review: +List: size(), get(..), remove(..) +Comparator +*/ + + +/** + * Definition of Interval: + * public class Interval { + * int start, end; + * Interval(int start, int end) { + * this.start = start; + * this.end = end; + * } + */ + +class Solution { + /** + * @param intervals: Sorted interval list. + * @return: A new sorted interval list. + */ + public List merge(List intervals) { + if (intervals == null || intervals.size() == 0) { + return intervals; + } + + // intervals.sort(new CustomComparator()); + Collections.sort(intervals, new Comparator(){ + public int compare(Interval a, Interval b){ + return a.start - b.start; + } + }); + //Merge + Interval pre = intervals.get(0); + Interval curr = null; + for (int i = 1; i < intervals.size(); i++) { + curr = intervals.get(i); + if (pre.end >= curr.start) { + pre.end = pre.end > curr.end ? pre.end : curr.end; + intervals.remove(i); + i--; + } else { + pre = curr; + } + } + + return intervals; + } +} diff --git a/Others/old records/LintCode-Backup/Merge Sorted Array II.java b/Others/old records/LintCode-Backup/Merge Sorted Array II.java new file mode 100644 index 0000000..24c2efe --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge Sorted Array II.java @@ -0,0 +1,99 @@ +长度已经固定。普通做法。 +``` +/* +33% Accepted +Merge two given sorted integer array A and B into a new sorted integer array. + +Example +A=[1,2,3,4] + +B=[2,4,5,6] + +return [1,2,2,3,4,4,5,6] + +Challenge +How can you optimize your algorithm if one array is very large and the other is very small? + +Tags Expand +Array Sorted Array + +*/ + +/* + 12.07.2015 + Since the 2 list A,B are fixed, just add everyting into it. + Basic implementation +*/ + +class Solution { + /** + * @param A and B: sorted integer array A and B. + * @return: A new sorted integer array + */ + public int[] mergeSortedArray(int[] A, int[] B) { + if (A == null || B == null) { + return A == null ? B : A; + } + int[] rst = new int[A.length + B.length]; + int indA = A.length - 1; + int indB = B.length - 1; + int i = rst.length - 1; + while (indA >= 0 && indB >= 0) { + if (A[indA] <= B[indB]) { + rst[i--] = B[indB--]; + } else { + rst[i--] = A[indA--]; + } + } + while (indA >= 0) { + rst[i--] = A[indA--]; + } + while (indB >= 0) { + rst[i--] = B[indB--]; + } + return rst; + } +} + +/* +Attemp1: Regular O(m+n) approach. Not optimizing anything. +*/ +class Solution { + /** + * @param A and B: sorted integer array A and B. + * @return: A new sorted integer array + */ + public ArrayList mergeSortedArray(ArrayList A, ArrayList B) { + if (A == null || A.size() == 0) { + return B; + } else if (B == null || B.size() == 0) { + return A; + } + ArrayList result = new ArrayList(); + int i = 0; + int j = 0; + while (i + j < A.size() + B.size()) { + if (i == A.size()) { + result.add(B.get(j)); + j++; + } else if (j == B.size()){ + result.add(A.get(i)); + i++; + } else { + if (A.get(i) <= B.get(j)) { + result.add(A.get(i)); + i++; + } else { + result.add(B.get(j)); + j++; + } + } + }//While + + return result; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Merge Sorted Array.java b/Others/old records/LintCode-Backup/Merge Sorted Array.java new file mode 100644 index 0000000..2fdf188 --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge Sorted Array.java @@ -0,0 +1,50 @@ +A够长,那么可以从A的尾部开始加新元素。 +注意,从尾部,是大数字优先的。 +``` +/* +Given two sorted integer arrays A and B, merge B into A as one sorted array. + +Note +You may assume that A has enough space (size that is greater or equal to m + n) to hold additional elements from B. The number of elements initialized in A and B are mand n respectively. + +Example +A = [1, 2, 3, empty, empty] B = [4,5] + +After merge, A will be filled as [1,2,3,4,5] + +Tags Expand +Array Sorted Array +*/ + +/* +Thinking process: +1. start from the end, track back. End index = m + n; +2. when ever check a position, need to do index-1, because index=m+n is the size of array. +3. Make sure to clean up the second array B. +*/ +class Solution { + /** + * @param A: sorted integer array A which has m elements, + * but size of A is m+n + * @param B: sorted integer array B which has n elements + * @return: void + */ + public void mergeSortedArray(int[] A, int m, int[] B, int n) { + // write your code here + int index = m + n; + while (m > 0 && n > 0) { + if (A[m - 1] > B[n - 1]) { + A[--index] = A[--m]; + } else { + A[--index] = B[--n]; + } + }//While + + while (n > 0) { + A[--index] = B[--n]; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Merge Two Sorted List.java b/Others/old records/LintCode-Backup/Merge Two Sorted List.java new file mode 100644 index 0000000..c793817 --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge Two Sorted List.java @@ -0,0 +1,69 @@ +E + +小的放前。每次比head大小。 +while过后,把没完的list一口气接上。 + +一开始建一个node用来跑路, 每次都存node.next = xxx。存一个dummy。用来return dummy.next. + +``` +/* +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. + +Example +Given 1->3->8->11->15->null, 2->null , return 1->2->3->8->11->15->null + +Tags Expand +Linked List + +Thinking process: +1. Merge sorted list, compare before add to node.next +2. when any of l1 or l2 is null, break out. +3. add the non-null list at the end of node. +4. return dummy.next. + +*/ +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param ListNode l1 is the head of the linked list + * @param ListNode l2 is the head of the linked list + * @return: ListNode head of linked list + */ + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } + ListNode dummy = new ListNode(0); + ListNode node = dummy; + while (l1 != null && l2 != null) { + if (l1.val <= l2.val) { + node.next = l1; + l1 = l1.next; + } else { + node.next = l2; + l2 = l2.next; + } + node = node.next; + }//while + if (l1 != null) { + node.next = l1; + } + if (l2 != null) { + node.next = l2; + } + return dummy.next; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Merge k Sorted Arrays.java b/Others/old records/LintCode-Backup/Merge k Sorted Arrays.java new file mode 100644 index 0000000..2a64dcc --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge k Sorted Arrays.java @@ -0,0 +1,97 @@ +由Merge k linked list想到,有办法找到每个node的sibling, 而int[]又不行,所以: +自己建立一个class 来存放必要信息 +``` +/* +Given k sorted integer arrays, merge them into one sorted array. + +Have you met this question in a real interview? Yes +Example +Given 3 sorted arrays: + +[ + [1, 3, 5, 7], + [2, 4, 6], + [0, 8, 9, 10, 11] +] +return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]. + +Challenge +Do it in O(N log k). + +N is the total number of integers. +k is the number of arrays. +Tags Expand +Heap Priority Queue +*/ + +/* + Thoughts: 12.10.2015 + Since we can't know the node's sibiling, as creating the prirority queue, + let's create a Node{val, x, y} + Then it's very similar to merge k sorted lists. + + border case: arrays == null. length == 0 //[]return empty list. +*/ + +public class Solution { + public class Node { + int val, x, y; + public Node(int val, int x, int y) { + this.val = val; + this.x = x; + this.y = y; + } + } + + public List mergekSortedArrays(int[][] arrays) { + List rst = new ArrayList(); + if (arrays == null || arrays.length == 0) { + return rst; + } + + PriorityQueue queue = new PriorityQueue(arrays.length, + new Comparator() { + public int compare(Node a, Node b){ + return a.val - b.val; + } + } + ); + + //init + for (int i = 0; i < arrays.length; i++) { + if (arrays[i].length != 0) { + queue.offer(new Node(arrays[i][0], i, 0)); + } + } + + Node node; + + while (!queue.isEmpty()) { + node = queue.poll(); + rst.add(node.val); + if (node.y < arrays[node.x].length - 1) { + queue.offer(new Node(arrays[node.x][node.y + 1], node.x, node.y + 1)); + } + } + + return rst; + + } +} + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Merge k Sorted Lists.java b/Others/old records/LintCode-Backup/Merge k Sorted Lists.java new file mode 100644 index 0000000..c1b2e19 --- /dev/null +++ b/Others/old records/LintCode-Backup/Merge k Sorted Lists.java @@ -0,0 +1,66 @@ +用Priorityqueue来排列所有list的头头。 +非常正规的。 + +记得k lists 需要是已经sort好的。 + +时间:n*O(logk) +PriorityQueue: logk +这个题目可以有好几个衍生: + +比如,如果k很大,一个机器上放不下所有的k list怎么办? +比如,如果Merge起来的很长,一个机器上放不下怎么办? +``` +/* +22% 通过 +Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. + +样例 +标签 Expand +Linked List Divide and Conquer Heap + +*/ + +/* + 12.10.2015 recap + Use queue to store the head of k lists. + First init with all heads. + Because the ListNode always has a link to its next sibiling, so it's easy to add that sibling back to queue. +*/ +public class Solution { + public ListNode mergeKLists(List lists) { + if (lists == null || lists.size() == 0) { + return null; + } + PriorityQueue queue = + new PriorityQueue(lists.size(), new Comparator(){ + public int compare(ListNode a, ListNode b){ + return a.val - b.val; + } + }); + + //populate queue with k lists' header + for (int i = 0; i < lists.size(); i++) { + if (lists.get(i) != null) { + queue.offer(lists.get(i)); + } + } + + ListNode dummy = new ListNode(0); + ListNode node = dummy; + while (!queue.isEmpty()) { + ListNode curr = queue.poll(); + node.next = curr; + + if (curr.next != null) { + queue.offer(curr.next); + } + + node = node.next; + } + + return dummy.next; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Middle of Linked List.java b/Others/old records/LintCode-Backup/Middle of Linked List.java new file mode 100644 index 0000000..9ba77bd --- /dev/null +++ b/Others/old records/LintCode-Backup/Middle of Linked List.java @@ -0,0 +1,59 @@ +快慢指针 + +不在乎slow是不是到底,因为fast肯定先到。 +确保fast, fast.next不是Null就好 + + +return slow +``` +/* +Find the middle node of a linked list. + +Have you met this question in a real interview? Yes +Example +Given 1->2->3, return the node with value 2. + +Given 1->2, return the node with value 1. + +Tags Expand +Linked List + +*/ +/* + Thoughts: + Practice LinkedList, fast and slow pointer +*/ + +public class Solution { + /** + * @param head: the head of linked list. + * @return: a middle node of the linked list + */ + public ListNode middleNode(ListNode head) { + if (head == null || head.next == null) { + return head; + } + + ListNode slow = head; + ListNode fast = head.next; + while (fast!= null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } +} + + +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Min Stack.java b/Others/old records/LintCode-Backup/Min Stack.java new file mode 100644 index 0000000..a04ea92 --- /dev/null +++ b/Others/old records/LintCode-Backup/Min Stack.java @@ -0,0 +1,61 @@ +E + +双Stack:一个正常stack,另一个minStack存当下level最小值. 注意维护minStack的变化 + + +``` +/* +Implement a stack with min() function, which will return the smallest number in the stack. + +It should support push, pop and min operation all in O(1) cost. + +Example +push(1) +pop() // return 1 +push(2) +push(3) +min() // return 2 +push(1) +min() // return 1 +Note +min operation will never be called if there is no number in the stack. + +Tags Expand +Stack + +Thoughts: +using 2 stacks: one regular, the other one trackes min element +MinStack (0 ~ i): for i elements in regular stack, at each ith, the min element is stored at MinStack(i). This means, there can be duplicated mins for different ith. + +Note: remember to check if minStack isEmpty(), empty stack does not have peek() +*/ + +public class MinStack { + private Stack stack; + private Stack minStack; + public MinStack() { + stack = new Stack(); + minStack = new Stack(); + } + + public void push(int number) { + stack.push(number); + if (minStack.isEmpty()) { + minStack.push(number); + } else { + minStack.push(minStack.peek() >= number ? number : minStack.peek()); + } + } + + public int pop() { + minStack.pop(); + return stack.pop(); + } + + public int min() { + return minStack.peek(); + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Minimum Path Sum.java b/Others/old records/LintCode-Backup/Minimum Path Sum.java new file mode 100644 index 0000000..a02831a --- /dev/null +++ b/Others/old records/LintCode-Backup/Minimum Path Sum.java @@ -0,0 +1,55 @@ +/* +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. + +Note +You can only move either down or right at any point in time. + +Example +Tags Expand +Dynamic Programming + +Thinking process: +1. Check null, lenght == 0 +2. Min Sum = sum of array. Initialization is a bit different, for example: each row element is added up from previous elemenet. (Not simple value assign from given grid) + - Assign (0,0) to grid[0][0] + - Row 1st row and 1st col, add up values +3. f(x,y) = sum of path value. f(x,y) = Math.Min(f(x-1,y), f(x, y-1)) +4. return f(r-1)(c-1) + +*/ + + +public class Solution { + /** + * @param grid: a list of lists of integers. + * @return: An integer, minimizes the sum of all numbers along its path + */ + public int minPathSum(int[][] grid) { + + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int row = grid.length; + int col = grid[0].length; + int[][] matrix = new int[row][col]; + matrix[0][0] = grid[0][0]; + //Add up for 1st row && 1st col + for (int i = 1; i < row; i++) { + matrix[i][0] = matrix[i - 1][0] + grid[i][0]; + } + for (int j = 1; j < col; j++) { + matrix[0][j] = matrix[0][j - 1] + grid[0][j]; + } + //Evaluate + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + matrix[i][j] = Math.min(matrix[i - 1][j], matrix[i][j - 1]) + + grid[i][j]; + } + } + return matrix[row - 1][col - 1]; + + } +} + + diff --git a/Others/old records/LintCode-Backup/Minimum Size Subarray Sum.java b/Others/old records/LintCode-Backup/Minimum Size Subarray Sum.java new file mode 100644 index 0000000..4e81edd --- /dev/null +++ b/Others/old records/LintCode-Backup/Minimum Size Subarray Sum.java @@ -0,0 +1,57 @@ +2 pointer: +一个做base, 每次动一格:i. +一个做前锋,加到满足条件为止。 +Note: 当sum >= s 条件在while里面满足时,end是多一个index的。所以result里面要处理好边缘情况:(end-1) 才是真的末尾位置,然后计算和开头的间隙: +(end - 1) - start + 1; +``` +/* +Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return -1 instead. + +Example +Given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length under the problem constraint. + +Challenge +If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). + +Tags Expand +Two Pointers Array +*/ + +/* +Thoughts: +Create a subarray range: (i,j). Use i as start and j as end. Check if within the range, sum >= s. +Shift the range every time: i += 1. +*/ + +public class Solution { + /** + * @param nums: an array of integers + * @param s: an integer + * @return: an integer representing the minimum size of subarray + */ + public int minimumSize(int[] nums, int s) { + if (nums == null || nums.length == 0) { + return -1; + } + int start = 0; + int end = 0; + int min = Integer.MAX_VALUE; + int sum = 0; + for (; start < nums.length; start++) { + while(end < nums.length && sum < s) { + sum += nums[end]; + end++; + } + if (sum >= s) { + min = Math.min(min, (end-1) - start + 1); + } + sum -= nums[start]; + } + return min == Integer.MAX_VALUE ? -1 : min; + } +} + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Minimum Subarray.java b/Others/old records/LintCode-Backup/Minimum Subarray.java new file mode 100644 index 0000000..10ed51f --- /dev/null +++ b/Others/old records/LintCode-Backup/Minimum Subarray.java @@ -0,0 +1,43 @@ +/* +Given an array of integers, find the subarray with smallest sum. + +Return the sum of the subarray. + +Example +For [1, -1, -2, 1], return -3 + +Note +The subarray should contain at least one integer. + +Tags Expand +Greedy LintCode Copyright Subarray Array + +Thoughts: +Note: sub-array has order. It's not sub-set +1. On each index: decide to add with nums.get(i), to use the new lowest value nums.get(i). That means: + If the new value is negative (it has decresing impact on sum) and the sum is larger than new value, just use the new value. + In another case, if sum has been nagative, so sum + new value will be even smaller, then use sum. +2. Every time compare the currMin with the overall minimum value, call it minRst. + +Note: remember to pre-set init value for curMin, minRst. +*/ + + +public class Solution { + /** + * @param nums: a list of integers + * @return: A integer indicate the sum of minimum subarray + */ + public int minSubArray(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + int curMin = nums.get(0); + int minRst = nums.get(0); + for (int i = 1; i < nums.size(); i++) { + curMin = Math.min(nums.get(i), curMin + nums.get(i)); + minRst = Math.min(curMin, minRst); + } + return minRst; + } +} \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Minimum Window Substring.java b/Others/old records/LintCode-Backup/Minimum Window Substring.java new file mode 100644 index 0000000..dfaabcb --- /dev/null +++ b/Others/old records/LintCode-Backup/Minimum Window Substring.java @@ -0,0 +1,112 @@ +/* +Given a string source and a string target, find the minimum window in source which will contain all the characters in target. + +Example +source = "ADOBECODEBANC" target = "ABC" Minimum window is "BANC". + +Note +If there is no such window in source that covers all characters in target, return the emtpy string "". + +If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in source. + +Challenge +Can you do it in time complexity O(n) ? + +Clarification +Should the characters in minimum window has the same order in target? + + - Not necessary. + +Tags Expand +Hash Table + +Thoughts: +The idea was from jiuzhang.com. +1. count target Characters: store each Character with HashMap:tCounter +2. Test against the source string. Here create another HashMap to keep records of the window:minWindowCounter +3. For any char appears in both target and source, count++ in the minWindowCounter. +4. As long as the number of a specific Character source.charAt(i) in minWindowCounter is less than that in tCounter, + use a count++ to keep the record. +5. Once count == target.length(), that means there is a candidate macthcing. Now we get into next level and look for the +minimum window. Note, this condition only meets once, and after found the solution, we can return the result, minWindow. +Note, at this point, we confirm target exist in source. Now we just test against target and find minimum window. +6. Now use a leftBound = 0, and loop through the source, as long as leftBound tCounter = new HashMap(); + for (int i = 0; i < target.length(); i++) { + Character c = target.charAt(i); + if (!tCounter.containsKey(c)) { + tCounter.put(c, 1); + } else { + tCounter.put(c, tCounter.get(c) + 1); + } + } + + HashMap minWindowCounter = new HashMap(); + int count = 0; + String rst = ""; + for (int i = 0; i < source.length(); i++) { + Character c = source.charAt(i); + if (!tCounter.containsKey(c)) { + continue; + } + + if (minWindowCounter.containsKey(c)) { + minWindowCounter.put(c, minWindowCounter.get(c) + 1); + } else { + minWindowCounter.put(c, 1); + } + + if (minWindowCounter.get(c) <= tCounter.get(c)) { + count++; + } + + //Once the target exists in soruce: count = target.length(), find the result + if (count == target.length()) { + int leftBound = 0; + while (leftBound < source.length()) { + Character cs = source.charAt(leftBound); + if (!minWindowCounter.containsKey(cs)) {//Not part of window + leftBound++; + continue; + } + if (minWindowCounter.get(cs) > tCounter.get(cs)) {//Can find shorter window + minWindowCounter.put(cs, minWindowCounter.get(cs) - 1); + leftBound++; + continue; + } + break; + } + rst = source.substring(leftBound, i + 1); + return rst; + } + } + return rst; + } + + public static void main(String[] args) { + Solution test = new Solution(); + String rst = test.minWindow("abcd", "ac"); + System.out.println("resutl is : " + rst); + } +} diff --git a/Others/old records/LintCode-Backup/MinimumDepthOfBinaryTree.java b/Others/old records/LintCode-Backup/MinimumDepthOfBinaryTree.java new file mode 100644 index 0000000..d5a063f --- /dev/null +++ b/Others/old records/LintCode-Backup/MinimumDepthOfBinaryTree.java @@ -0,0 +1,64 @@ +/* +Given a binary tree, find its minimum depth. + +The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. + +Example +Given a binary tree as follow: + + 1 + + / \ + + 2 3 + + / \ + + 4 5 + +The minimum depth is 2 + +Tags Expand +Depth First Search + +Thinking Process: +Note: a little different from maxDepth: +If 1,#,2: the left route 1-# does not count as a path, so the minDepth is actually 2 in this example. +We need a helper function to calculate the minimum. +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param root: The root of binary tree. + * @return: An integer. + */ + //recursive: + public int minDepth(TreeNode root) { + if (root == null) { + return 0; + } + return getMin(root); + } + + public int getMin(TreeNode root) { + if (root == null) { + return Integer.MAX_VALUE; + } + if (root.left == null && root.right == null) { + return 1; + } + return Math.min(getMin(root.left), getMin(root.right)) + 1; + } +} + diff --git a/Others/old records/LintCode-Backup/NQueens.java b/Others/old records/LintCode-Backup/NQueens.java new file mode 100644 index 0000000..6141215 --- /dev/null +++ b/Others/old records/LintCode-Backup/NQueens.java @@ -0,0 +1,220 @@ +把NQueen board想象成一个1D array。 +index就是col number +值就是row number. + +validate n queue的时候 target row# +1. array 里面不能有 target row# +2. diagnal. 记得公式: + row1 - row2 == col1 - col2. Diagnal elelment.fail + row1 - row2 == -(col1 - col2). Diagnal element. fail + +``` +/* +The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that +no two queens attack each other. + +Given an integer n, return all distinct solutions to the n-queens puzzle. + +Each solution contains a distinct board configuration of the n-queens' placement, +where 'Q' and '.' both indicate a queen and an empty space respectively. + +For example, +There exist two distinct solutions to the 4-queens puzzle: + +[ + [".Q..", // Solution 1 + "...Q", + "Q...", + "..Q."], + + ["..Q.", // Solution 2 + "Q...", + "...Q", + ".Q.."] +] +Hide Tags Backtracking + + +*/ + +/* + Recap: 12.08.2015 + NQueen: turns into a 1D array of row#'s. What are all of the possible combinations? + Validate the board: + With 1 potential canddate, a row# to put in the array + 1. the 1D array cannot have duplicate of the candidate + 2. check diagnals: + row1 - row2 == col1 - col2. Diagnal elelment.fail + row1 - row2 == -(col1 - col2). Diagnal element. fail + That is: delta_row = Q1 row - Q2 row + delta_col = Q1 col - Q2 col + Let delta_row = the difference in rows between the two queens, and delta_col = the difference in columns. + The two queens will be on the same diagonal if delta_row == delta_col or delta_row == -delta_col + + Create the board: + carete 2d arraylist based on the 1-D array of row#'s + + corner case: if n<=2, no solution +*/ + +class Solution { + + public ArrayList> solveNQueens(int n) { + ArrayList> rst = new ArrayList>(); + if (n <= 0) { + return rst; + } + ArrayList list = new ArrayList(); //1D array + helper(rst, list, n); + + return rst; + } + + /* + Validate the board with given input. + */ + public boolean validate(ArrayList list, int rowNum) { + int colNum = list.size(); // the column that rowNum is going to be put on + for (int col = 0; col < list.size(); col++) { + //check row + if (list.get(col) == rowNum) { + return false; + } + //check diagnal + //q1 col - newQ col == q1 row - newQ row + if (col - colNum == list.get(col) - rowNum) { + return false; + } + //q1 col - newQ col == -(q1 row - newQ row) + if (col - colNum == -(list.get(col) - rowNum)) { + return false; + } + } + return true; + } + + public ArrayList createBoard(ArrayList list){ + ArrayList board = new ArrayList(); + for (int row = 0; row < list.size(); row++) { + StringBuffer sb = new StringBuffer(); + for (int col : list) { + if (row == col) { + sb.append("Q"); + } else { + sb.append("."); + } + } + board.add(sb.toString()); + } + return board; + } + + + public void helper(ArrayList> rst, ArrayList list, int n){ + if (list.size() == n) { + rst.add(createBoard(list)); + return; + } + //For next Queen, which row to put? Now do recursive: + for (int i = 0; i < n; i++) { + if (validate(list, i)) { + list.add(i); + helper(rst, list, n); + list.remove(list.size() - 1); + } + } + } +}; + + + +//Older version: the naming in validate() is confusing +/* +Thinking process: +1. Choose / Not choose concept. +2. N-Queue facts: + Each column has 1 Q. Each row has 1 Q. + That is: each column has 1 Q, which can be present as a row number. + Use a 1-D array: index is column number, value is row number +3. When adding a new row Number into the 1-D array, validate it. +4. Use same procedure in 'permutaions' problem. + The 1-D array 'cols' will be filled with all kinds of combination from 1 ~ n. + Only when cols.size() == n, return a solution +5. When returnning the solution, return the format as a board. ArrayList +*/ +import java.util.*; +class NQueens { + /** + * Get all distinct N-Queen solutions + * @param n: The number of queens + * @return: All distinct solutions + * For example, A string '...Q' shows a queen on forth position + */ + ArrayList> solveNQueens(int n) { + ArrayList> rst = new ArrayList>(); + if (n <= 0) { + return rst; + } + search(n, new ArrayList(), rst); + return rst; + } + + ArrayList createBoard(ArrayList cols) { + ArrayList solution = new ArrayList(); + for (int i = 0; i < cols.size(); i++) { + StringBuffer sb = new StringBuffer(); + for (int j = 0; j < cols.size(); j++){ + if (j == cols.get(i)) { + sb.append( "Q"); + } else { + sb.append( "."); + } + } + solution.add(sb.toString()); + } + return solution; + } + + boolean isValid (ArrayList cols, int col) { + int row = cols.size(); + for (int i = 0; i < row; i++) { + if (cols.get(i) == col ) { + return false; + } + //Check diagnal: Q1_row - Q2_row == Q1_col - Q2_col + //In this case: + //col: the target queen's column# + //cols.get(i): the target queen's row# + //We compare them with (row: current max_column#) and (i: current row#), to check if valid + if (i - cols.get(i) == row - col) { + return false; + } + if (i + cols.get(i) == row + col) { + return false; + } + } + return true; + } + + void search(int n, ArrayList cols, ArrayList> rst) { + if (cols.size() == n) { + rst.add(createBoard(cols)); + return; + } + for (int i = 0; i < n; i++) { + if (!isValid(cols, i)) { + continue; + } + cols.add(i); + search(n, cols, rst); + cols.remove(cols.size() - 1); + } + } + + public static void main(String[] args){ + NQueens test = new NQueens(); + test.solveNQueens(4); + } + +}; +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/NQueensII.java b/Others/old records/LintCode-Backup/NQueensII.java new file mode 100644 index 0000000..756590c --- /dev/null +++ b/Others/old records/LintCode-Backup/NQueensII.java @@ -0,0 +1,70 @@ +当list.size() == n 的时候,说明找到了一个Solution。 +直接add 一个什么乱起八糟的东西进rst都可以。 +然后最后要的是 rst.size() = # of solutons +``` +/* +Follow up for N-Queens problem. + +Now, instead outputting board configurations, return the total number of distinct solutions. + +Example +For n=4, there are 2 distinct solutions. + +Tags Expand +Recursion + +Thoughts: +Exact same as NQueens, except we don't print the map. Instead, simply add the record in rst. +At the end, return rst.size(), which would be unique answer. +*/ +class Solution { + /** + * Calculate the total number of distinct N-Queen solutions. + * @param n: The number of queens. + * @return: The total number of distinct solutions. + */ + public int totalNQueens(int n) { + ArrayList> rst = new ArrayList>(); + if (n <= 0) { + return 0; + } + search(n, new ArrayList(), rst); + return rst.size(); + } + + boolean isValid (ArrayList cols, int col) { + int row = cols.size(); + for (int i = 0; i < row; i++) { + if (cols.get(i) == col ) { + return false; + } + if (i - cols.get(i) == row - col) { + return false; + } + if (i + cols.get(i) == row + col) { + return false; + } + } + return true; + } + + void search(int n, ArrayList cols, ArrayList> rst) { + if (cols.size() == n) { + rst.add(cols); + return; + } + for (int i = 0; i < n; i++) { + if (!isValid(cols, i)) { + continue; + } + cols.add(i); + search(n, cols, rst); + cols.remove(cols.size() - 1); + } + } + +}; + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Next Permutation.java b/Others/old records/LintCode-Backup/Next Permutation.java new file mode 100644 index 0000000..3d4c64c --- /dev/null +++ b/Others/old records/LintCode-Backup/Next Permutation.java @@ -0,0 +1,87 @@ +/* +Given a list of integers, which denote a permutation. + +Find the next permutation in ascending order. + +Have you met this question in a real interview? Yes +Example +For [1,3,2,3], the next permutation is [1,3,3,2] + +For [4,3,2,1], the next permutation is [1,2,3,4] + +Note +The list may contains duplicate integers. + +Tags Expand +LintCode Copyright Permutation + +Thoughts: +Not much info are given. Need to ask. It looks like: +We are dong permutation on the given numbers, and find out what's next permutation array based on given order. + +Ascending order: Permutations that permutation(i) < permutation(i + 1) + +Goal: +To find the next smallest permutation. +1. Find the last increasing index (a peek before decresing): k +2. Find the first bigger permutation: Well, it turns out this first bigger index is always on right side of k. + Note: we are trying to get the least significant change on the given permuation. + Next Step: reverse (k+1, end). This is because: before the change, right side of K will be the largest possible combination. After swapping K, we need the right side to be the smallest combination. (Well, this is my understanding....Still a bit confused on why we take these steps in this problem) +*/ + + +public class Solution { + /** + * @param nums: an array of integers + * @return: return nothing (void), do not return anything, modify nums in-place instead + */ + //Revers the given part of a int[] + public int[] reverse(int start, int end, int[] nums) { + for (int i = start, j = end; i < j; i++,j--) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } + return nums; + } + + public int[] nextPermutation(int[] nums) { + if (nums == null || nums.length == 0) { + return nums; + } + //Find last increasing point before decreasing. nums[k] < nums[k+1] + int k = -1; + for (int i = nums.length - 2; i >= 0; i--) { + if (nums[i] < nums[i + 1]) { + k = i; + break; + } + } + if (k == -1) { + return reverse(0, nums.length - 1, nums); + } + //Find first bigger point, from right to left + int bigIndex = -1; + for (int i = nums.length - 1; i >= 0; i--) { + if (nums[i] > nums[k]) { + bigIndex = i; + break; + } + } + //1. Swap bigger index with k; 2. Reverse the right side of k. [Try to make the smallest next permutation] + int temp = nums[k]; + nums[k] = nums[bigIndex]; + nums[bigIndex] = temp; + + return reverse(k + 1, nums.length - 1, nums); + } + + + +} + + + + + + diff --git a/Others/old records/LintCode-Backup/Nim Game.java b/Others/old records/LintCode-Backup/Nim Game.java new file mode 100644 index 0000000..11866ab --- /dev/null +++ b/Others/old records/LintCode-Backup/Nim Game.java @@ -0,0 +1,45 @@ +著名Nim游戏。 +写一些,发现n=4,5,6,7,8...etc之后的情况有规律性。 +最终很简单n%4!=0就可以了 +``` +/* +You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones. + +Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap. + +For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend. + +Hint: + +If there are 5 stones in the heap, could you figure out a way to remove the stones such that you will always be the winner? + + +Hide Similar Problems (M) Flip Game II + +*/ + + +/* + Thoughts: + If n = 4, we can do the following: + 1 0 0 0 + 1 1 0 0 + 1 1 1 0 + But we'll fail. + + n = 5, we pick 1, 2nd player gets n = 4. + n = 6, we pick 2, 2nd player gets n = 4. + n = 7, we pick 3, 2nd player gets n = 4. + n = 8, regarless whatever we pick, the opponent can make 1st gets n = 4, we fail. + ... + ... + whenever n % 4 = 0, 1st player fail. + +*/ + +public class Solution { + public boolean canWinNim(int n) { + return n % 4 != 0; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Nth to Last Node in List.java b/Others/old records/LintCode-Backup/Nth to Last Node in List.java new file mode 100644 index 0000000..daa135a --- /dev/null +++ b/Others/old records/LintCode-Backup/Nth to Last Node in List.java @@ -0,0 +1,61 @@ +先找到nth node +然后head开始跑。 + +node 到底,而head ~ node刚好是 n 距离。所以head就是要找的last nth +``` +/* +Find the nth to last element of a singly linked list. + +The minimum number of nodes in list is n. + +Example +Given a List 3->2->1->5->null and n = 2, return node whose value is 1. + +Tags Expand +Cracking The Coding Interview Linked List + +Thinking process: +1. Find nth node in normal order. +2. Have a head at index0. +3. Move both head and nth node. WHen nth node hit null/end, then the moving head is the nth to last node in list. +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @param n: An integer. + * @return: Nth to last node of a singly linked list. + */ + ListNode nthToLast(ListNode head, int n) { + if (head == null || n < 0) { + return null; + } + int count = 0; + ListNode node = head; + while (node != null && count < n) { + node = node.next; + count++; + } + while (node != null) { + node = node.next; + head = head.next; + } + return head; + } +} + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Number Triangles.java b/Others/old records/LintCode-Backup/Number Triangles.java new file mode 100644 index 0000000..d55d126 --- /dev/null +++ b/Others/old records/LintCode-Backup/Number Triangles.java @@ -0,0 +1,98 @@ +/* +Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. + +Note +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. + +Example +For example, given the following triangle + +[ + [2], + [3,4], + [6,5,7], + [4,1,8,3] +] +The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). + +Tags Expand +Dynamic Programming + +Thinking process: +1. Bottom-up + - Start from the bottom row, get all values of this row. Note: in triangle, height = cols at each row. So row X has X numbers. + - Start from (n - 1)th row and run up: calculate min from lower level + current node value. + - Depending what is wanted, here we use a 2D int arraya and return the min sum. +*/ + +public class Solution { + /** + * @param triangle: a list of lists of integers. + * @return: An integer, minimum path sum. + */ + //Bottom - up + public int minimumTotal(ArrayList> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + int n = triangle.size(); + int[][] sum = new int[n][n]; + for (int i = 0; i < n; i++) { + sum[n - 1][i] = triangle.get(n - 1).get(i); + } + for (int i = n - 2; i >= 0; i--) { + for (int j = 0; j <= i; j++) { + sum[i][j] = Math.min(sum[i + 1][j], sum[i + 1][j + 1]) + triangle.get(i).get(j); + } + } + return sum[0][0]; + } +} + +/* +2. Memorize Search + - Go through all nodes and initialize with Integer.MAX_VALUE; + - Search from top: thislevel-current = Math.min(nextlevel-current, nextlevel-next) + thislevel-current + - During the Search Helper, when a node has been set previously, just return this value because this min value has been pre-calculated. + If row is >= triangle.size(), return 0. + - This method can actually calculate the min sum from bottom to any point in the triangle. +*/ + +public class Solution { + /** + * @param triangle: a list of lists of integers. + * @return: An integer, minimum path sum. + */ + + //Version 2 : Memorize Search + private int n; + private ArrayList> triangle; + public int minimumTotal(ArrayList> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + this.n = triangle.size(); + this.triangle = triangle; + int[][] sum = new int[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j <= i; j++) { + sum[i][j] = Integer.MAX_VALUE; + } + } + return searchHelper(0, 0, sum); + } + + public int searchHelper(int r, int c, int[][] sum) { + if (r >= this.n) { + return 0; + } + if (sum[r][c] != Integer.MAX_VALUE) { + return sum[r][c]; + } + sum[r][c] = Math.min(searchHelper(r + 1, c, sum), searchHelper(r + 1, c + 1, sum)) + this.triangle.get(r).get(c); + return sum[r][c]; + } +} + + + diff --git a/Others/old records/LintCode-Backup/Number of Airplane in the sky.java b/Others/old records/LintCode-Backup/Number of Airplane in the sky.java new file mode 100644 index 0000000..32ffe56 --- /dev/null +++ b/Others/old records/LintCode-Backup/Number of Airplane in the sky.java @@ -0,0 +1,72 @@ +/* +http://www.lintcode.com/en/problem/number-of-airplanes-in-the-sky/ +Given an interval list which are flying and landing time of the flight. How many airplanes are on the sky at most? + +Example +For interval list [[1,10],[2,3],[5,8],[4,7]], return 3 + +Note +If landing and flying happens at the same time, we consider landing should happen at first. + +Tags Expand +LintCode Copyright Array Interval +*/ + + +/* +Thoughts: same as the number of meeting. +Use a Point class {time, flag} and mark all time spot, and use a min-heap(PriorityQueue) to sort it. + +Note: LintCode forces me to put '10' in PriorityQueue constructor? +*/ +/** + * Definition of Interval: + * public classs Interval { + * int start, end; + * Interval(int start, int end) { + * this.start = start; + * this.end = end; + * } + */ + +class Solution { + class Point { + int x; + int flag; + public Point(int x, int flag) { + this.x = x; + this.flag = flag; + } + } + /** + * @param intervals: An interval array + * @return: Count of airplanes are in the sky. + */ + public int countOfAirplanes(List airplanes) { + if (airplanes == null || airplanes.size() == 0) { + return 0; + } + PriorityQueue queue = new PriorityQueue(10, + new Comparator(){ + public int compare(Point a, Point b) { + return a.x - b.x; + } + }); + for (Interval interval : airplanes) { + queue.offer(new Point(interval.start, 1)); + queue.offer(new Point(interval.end, -1)); + } + int count = 0; + int max = 0; + while (!queue.isEmpty()) { + Point p = queue.poll(); + count+= p.flag; + while (!queue.isEmpty() && queue.peek().x == p.x) { + p = queue.poll(); + count += p.flag; + } + max = Math.max(count, max); + } + return max; + } +} diff --git a/Others/old records/LintCode-Backup/Number of Islands II.java b/Others/old records/LintCode-Backup/Number of Islands II.java new file mode 100644 index 0000000..04bf01a --- /dev/null +++ b/Others/old records/LintCode-Backup/Number of Islands II.java @@ -0,0 +1,110 @@ +/* +Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator. + +Have you met this question in a real interview? Yes +Example +Given n = 3, m = 3, array of pair A = [(0,0),(0,1),(2,2),(2,1)]. + +return [1,1,2,2]. + +Note +0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent. + +Tags Expand +Union Find +*/ + +/* +Thoughts: +Each pos(x,y) turns that sea spot into a island spot. +Image each isleand spot is a node in the graph, and each island(many island spots) has a root parent. +In for loop, try to add operators into the matrix one after another. + Every time when adding a new island spot, check its sourandings and see if there are islands existed. + If souranding island was land: + To check if the surrouding spot are on common island (use find and union). + Since the operator spot was sea, the it's root parent is itself. Then, souranding spot has different island root, + they will surely have differet root parent, but they will do after they connect, so we do count--. + +On the otherhand, if surrounding was just sea, then count++ is natural + +Note: +1. Know how to write up simple union find class +2. Convert 2D array into 1D +*/ + +/** + * Definition for a point. + * class Point { + * int x; + * int y; + * Point() { x = 0; y = 0; } + * Point(int a, int b) { x = a; y = b; } + * } + */ +public class Solution { + class UnionFind { + HashMap map = new HashMap(); + public UnionFind(int length) { + for (int i = 0; i < length; i++) { + map.put(i,i); + } + } + public int find(int target) { + int parent = map.get(target); + while (parent != map.get(parent)) { + parent = map.get(parent); + } + return parent; + } + + public void union(int x, int y) { + int findX = find(x); + int findY = find(y); + if (findX != findY) { + map.put(findX, findY); + } + } + } + /** + * @param n an integer + * @param m an integer + * @param operators an array of point + * @return an integer array + */ + public List numIslands2(int n, int m, Point[] operators) { + List rst = new ArrayList(); + if (operators == null || operators.length == 0) { + return rst; + } + int count = 0; + int[] island = new int[m*n]; + UnionFind uf = new UnionFind(m*n); + int[] xs = {-1, 1, 0, 0}; + int[] ys = {0, 0, -1, 1}; + for (int i = 0; i < operators.length; i++) { + int x = operators[i].x; + int y = operators[i].y; + int pos = x * m + y; + count++; + if (island[pos] != 1) { + island[pos] = 1; + for (int j = 0; j < 4; j++) { + int nx = x + xs[j]; + int ny = y + ys[j]; + int newPos = nx * m + ny; + if (nx >= 0 && nx < n && ny >= 0 && ny < m && island[newPos] == 1) {//when new position is land + int findA = uf.find(pos); + int findB = uf.find(newPos); + if (findA != findB) { + count--; + uf.union(pos, newPos); + } + } + } + } + rst.add(count); + } + + return rst; + } +} diff --git a/Others/old records/LintCode-Backup/Number of Islands.java b/Others/old records/LintCode-Backup/Number of Islands.java new file mode 100644 index 0000000..dd4dcbe --- /dev/null +++ b/Others/old records/LintCode-Backup/Number of Islands.java @@ -0,0 +1,118 @@ +M + +方法1: 两个for loop brutle force。 DFS把每个跟1相关的都Mark一遍.生成一个island. + +方法2: (暂时没有写union-find的解) +可以用union-find, 就像Number of island II 一样。 +只不过这个不Return list, 而只是# of islands + +``` +/* +Given a boolean 2D matrix, find the number of islands. + +Example +Given graph: + +[ + [1, 1, 0, 0, 0], + [0, 1, 0, 0, 1], + [0, 0, 0, 1, 1], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 1] +] +return 3. + +Note +0 is represented as the sea, 1 is represented as the island. +If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent. + +*/ + +/* + 12.12.2015 recap + We are checking if a sets of adjacent nodes are int the same set + We union all neighbors + Generate the list of islands: actually return the # of islands + + AND yes, this is doable. Number of island II is using union-find +*/ + +/* + +Thoughts: +1. Use a 2D integer matrix to map the islands, by default the 2D [][] is all 0. +2. When the matrix point is 0, means it has not been checked. Check it against the grid. +3. Whenever there is a match, assign mark to that point. +4. Only increase mark when all the recursion finishes. +5. return mark - 1 + +*/ +public class Solution { + int[][] matrix; + int mark; + /** + * @param grid a boolean 2D matrix + * @return an integer + */ + public int numIslands(boolean[][] grid) { + if (grid == null || grid.length ==0 || grid[0].length == 0) { + return 0; + } + matrix = new int[grid.length][grid[0].length]; + mark = 1; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + mark = check(i, j, mark, grid) ? (mark + 1) : mark; + } + } + + return mark - 1; + } + + public boolean check(int x, int y, int mark, boolean[][] grid) { + if (x >= 0 && x < matrix.length && y >= 0 && y < matrix[0].length) { + if (matrix[x][y] == 0 && grid[x][y]) { + matrix[x][y] = mark; + check(x + 1, y, mark, grid); + check(x - 1, y, mark, grid); + check(x, y + 1, mark, grid); + check(x, y - 1, mark, grid); + return true; + } + } + return false; + } +} + + +//from leetcode: +public class Solution { + + public int numIslands(char[][] grid) { + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int count = 0; + for(int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + count = mark(i, j, grid)? (count + 1) : count; + } + } + return count; + } + + public boolean mark(int i, int j, char[][] grid) { + if (i >= 0 && i < grid.length && j >= 0 && j < grid[0].length) { + if (grid[i][j] == '1') { + grid[i][j] = 'M'; + mark(i - 1, j, grid); + mark(i + 1, j, grid); + mark(i, j - 1, grid); + mark(i, j + 1, grid); + return true; + } + } + return false; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/O(1) Check Power of 2.java b/Others/old records/LintCode-Backup/O(1) Check Power of 2.java new file mode 100644 index 0000000..8da73e3 --- /dev/null +++ b/Others/old records/LintCode-Backup/O(1) Check Power of 2.java @@ -0,0 +1,34 @@ +/* +Using O(1) time to check whether an integer n is a power of 2. +Example +For n=4, return true + +For n=5, return false + +Challenge +O(1) time + +Tags Expand +Binary + +Thinking process: +Any integer that's power of 2, follows one pattern. They are all: 1000000000....000 format. +so (n - 1) becomes: 01111111111...111. +If bit-and them togeter, it will be 0. + +*/ + +class Solution { + /* + * @param n: An integer + * @return: True or false + */ + public boolean checkPowerOf2(int n) { + if (n <= 0) { + return false; + } + return (n & (n - 1)) == 0; + } +}; + + diff --git a/Others/old records/LintCode-Backup/Palindrome Linked List.java b/Others/old records/LintCode-Backup/Palindrome Linked List.java new file mode 100644 index 0000000..418294b --- /dev/null +++ b/Others/old records/LintCode-Backup/Palindrome Linked List.java @@ -0,0 +1,115 @@ +Palindrome都是要两边回溯相等。 +linkedlist不能reverse iterating, 那么就reverse the list, 从中间开花作比较。 +``` +/* +Implement a function to check if a linked list is a palindrome. + +Example +Given 1->2->1, return true + +Challenge +Could you do it in O(n) time and O(1) space? + +Tags Expand +Linked List +*/ + +/* + Thoughts: + Reverse the 2nd half of the list, save it to right node + Then compare left and right. + THey should be the same. + + How do we know it's odd or even number of nodes? + ( + At the end, if F.next == null, even. + If F == null, odd + Well, need a global bool isEven variable + - If odd: let = [0 , mid], right = [mid, end] + - If even: left = [0,mid], right = [mid +1, end] + ) + The odd/even actually does not matter: regardless which middle is returned, always reverse [mid.next, end] + - p1 has 1 extra element, p2 will loop to null first. That's okay. + - p1 and p2 size same, p2 will loop till end, null. + That is, if somewhere they break, and p2 is not loopped to null yet, that means, the palindrome fails + 1. find mid. + 2. reverse 2nd half of the list. + 3. while loop to compare the node if they are all equal. if not false. + + border case: if head == null, or head.next == null, just true. +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + + public boolean isPalindrome(ListNode head) { + if (head == null || head.next == null) { + return true; + } + //Find middle + ListNode mid = findMiddle(head); + //Reverse and return right side + ListNode right = reverse(mid.next); + mid.next = null; + ListNode left = head; + while (left != null && right != null) { + if (left.val != right.val) { + return false; + } + left = left.next; + right = right.next; + } + //It's possible that left&&right both finishes; or just right finishes. Both cases are returnning true. + return right == null; + } + + public ListNode findMiddle(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public ListNode reverse(ListNode head) { + ListNode dummy = new ListNode(0); + ListNode reversedList = dummy; + while (head != null) { + //store head.next for iteration usage + ListNode temp = head.next; + //insert head into the reservedList, at starting spot. + head.next = reversedList.next; + reversedList.next = head; + //Move to next node + head = temp; + } + return dummy.next; + } +} + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Palindrome Partitioning II.java b/Others/old records/LintCode-Backup/Palindrome Partitioning II.java new file mode 100644 index 0000000..447313e --- /dev/null +++ b/Others/old records/LintCode-Backup/Palindrome Partitioning II.java @@ -0,0 +1,57 @@ +Double for loop 检查每种substring string (i~j). 若i,j相邻或者同点,那么肯定isPal;否则,i,j之间的(i+1, j-1)一定得isPal。 +看上去,在检查i,j的时候,中间按的(i+1, j-1)怎么可能先知道? 其实不然..在j慢慢长大的时候,所有的0~j的substring都检查过。所以isPal[i+1][j-1]一定是已经知道结果的。 + +okay.那么假如以上任意一种情况成立,也就是说isPal[i][j] == true。那就要判断,切到第一层循环参数j的末尾点时,有多少种切法? +想法很顺:我们naturally会想到,把i之前的cut加上i~j之间发生的不就好了。 +反正现在j不变,现在就看吧i定在哪里,cut[i - 1]是否更小/最小; 再在cut[i-1]基础上+1就完了。 + 当然,如果i==0, 而 i~j又是isPal,那没啥好谈的,不必切,0刀。 + +最终,刷到cut[s.length() - 1] 也就是最后一点。 return的理所应当。 +``` +/* +Given a string s, cut s into some substrings such that every substring is a palindrome. +Return the minimum cuts needed for a palindrome partitioning of s. +Example +For example, given s = "aab", +Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut. +Tags Expand +Dynamic Programming +Thinking process: +DP problem. +Use a isPal to record if any [i ~ j] is Palindrome, true/false + for any char s[i] and s[j], if s[i] == s[j], then need to check if [i + 1, j - 1] is Palindrome, which is just isPal[i + 1, j - 1]. +Use cut[j] to record the minimal cut from char index [0 ~ j] + by default, cut[j] = j because the worst condition is cut j times at each charactor: none 2+ character palindrome, and split into individual chars. + update cut[j] by comparing existing cut[j] and (cut[i - 1] + 1). +At the end, return cut[s.length() - 1]. +*/ + +public class Solution { + /** + * @param s a string + * @return an integer + */ + public int minCut(String s) { + if (s == null || s.length() == 0) { + return 0; + } + int length = s.length(); + boolean[][] isPal = new boolean[length][length]; + int[] cut = new int[length]; + for (int j = 0; j < length; j++) { + cut[j] = j; + for (int i = 0; i <= j; i++) { + if (s.charAt(i) == s.charAt(j) && (j - i <= 1 || isPal[i + 1][j - 1])) { + isPal[i][j] = true; + if (i > 0) { + cut[j] = Math.min(cut[j], cut[i - 1] + 1); + } else { + cut[j] = 0; + } + } + }//end i_for + }//end for j_for + return cut[length - 1]; + } +}; +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Palindrome Partitioning.java b/Others/old records/LintCode-Backup/Palindrome Partitioning.java new file mode 100644 index 0000000..95dff80 --- /dev/null +++ b/Others/old records/LintCode-Backup/Palindrome Partitioning.java @@ -0,0 +1,73 @@ +很清楚的DFS Backtracking. +在遍历str的时候,考虑从每个curr spot 到 str 结尾,是能有多少种palindorme? 那就从curr spot当个字符开始算,开始back tracing. +如果所选不是palindrome, 那move on. +若所选的确是palindrome, 加到path里面,DFS去下个level,等遍历到了结尾,这就产生了一种分割成palindrome的串。 +每次DFS结尾,要把这一层加的所选palindrome删掉,backtracking嘛。 +``` +/* +Given a string s, partition s such that every substring of the partition is a palindrome. +Return all possible palindrome partitioning of s. +Example +given s = "aab", +Return + [ + ["aa","b"], + ["a","a","b"] + ] +Tags Expand +Backtracking +Thinking process: +1. Know how to write isPalindrome +2. Back tracking: + check partial string + add it + recursive call + remove it. +*/ + +public class Solution { + /** + * @param s: A string + * @return: A list of lists of string + */ + public List> partition(String s) { + List> rst = new ArrayList>(); + if (s == null || s.length() < 0) { + return rst; + } + ArrayList path = new ArrayList(); + helper(s, path, 0, rst); + return rst; + } + //Check Palindrome + public boolean isPalindrome(String s){ + int start = 0; + int end = s.length() - 1; + while (start < end) { + if (s.charAt(start) != s.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } + //helper: + public void helper(String s, ArrayList path, int pos, + List> rst) { + if (pos == s.length()) { + rst.add(new ArrayList(path)); + return; + } + for (int i = pos + 1; i <= s.length(); i++) {//i is used in s.sbustring(pos, i), which can equal to s.length() + String prefix = s.substring(pos, i); + if (!isPalindrome(prefix)) { + continue; + } + path.add(prefix); + helper(s, path, i, rst); + path.remove(path.size() - 1); + } + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Partition Array by Odd and Even.java b/Others/old records/LintCode-Backup/Partition Array by Odd and Even.java new file mode 100644 index 0000000..27c784f --- /dev/null +++ b/Others/old records/LintCode-Backup/Partition Array by Odd and Even.java @@ -0,0 +1,51 @@ +/* +Partition an integers array into odd number first and even number second. + +Example +Given [1, 2, 3, 4], return [1, 3, 2, 4] + +Challenge +Do it in-place. + +Tags Expand +Two Pointers Array + +Thougths: +Use two pointers: nextOddPt, firstEvenPt +1. Whenever nextOddPt > firstEvenPt, swapt them +2. Incrase nextOddPt in a for loop +Note: +After each swap, have to start checking again from beginning-switching point, which will be firstEvenPt. Need to set i = firstEvenPt. +However, since for loop will do i++, we need to set i = firstEvenPt - 1; +And firstEvenPt only needs to be update once so use -1 to check if it's set. +*/ + +public class Solution { + /** + * @param nums: an array of integers + * @return: nothing + */ + public void partitionArray(int[] nums) { + if (nums == null || nums.length == 0){ + return; + } + int nextOddPt = -1; + int firstEvenPt = -1; + for (int i = 0; i < nums.length; i++) { + if (nums[i] % 2 == 1) { + nextOddPt = i; + } else { + if (firstEvenPt == -1) { + firstEvenPt = i; + } + } + if (nextOddPt > firstEvenPt && firstEvenPt != -1) { + int temp = nums[nextOddPt]; + nums[nextOddPt] = nums[firstEvenPt]; + nums[firstEvenPt] = temp; + i = firstEvenPt - 1; + firstEvenPt = -1; + } + } + } +} diff --git a/Others/old records/LintCode-Backup/Partition Array.java b/Others/old records/LintCode-Backup/Partition Array.java new file mode 100644 index 0000000..5ded8b4 --- /dev/null +++ b/Others/old records/LintCode-Backup/Partition Array.java @@ -0,0 +1,74 @@ +Partition Array根据pivot把array分成两半。 +从array两边开始缩进。while loop到遍历完。非常直白的implement。 +注意low/high,或者叫start/end不要越边界 +O(n) + +Quick sort的基础。 +``` +/* +Given an array nums of integers and an int k, partition the array (i.e move the elements in "nums") such that: + +All elements < k are moved to the left +All elements >= k are moved to the right +Return the partitioning index, i.e the first index i nums[i] >= k. + +Example +If nums=[3,2,2,1] and k=2, a valid answer is 1. + +Note +You should do really partition in array nums instead of just counting the numbers of integers smaller than k. + +If all elements in nums are smaller than k, then return nums.length + +Challenge +Can you partition the array in-place and in O(n)? + +Tags Expand +Two Pointers Sort Array + +Thoughts: +Two pointer sort, still similar to quick sort. +Move small to left and large to right. +When the two pinter meets, that's crossing point about pivot k + +*/ +public class Solution { + /** + *@param nums: The integer array you should partition + *@param k: As description + *return: The index after partition + */ + public int partitionArray(int[] nums, int k) { + if (nums == null || nums.length == 0) { + return 0; + } + return helper(nums, 0, nums.length - 1, k); + } + + public void swap(int[] nums, int x, int y){ + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } + + public int helper(int[] nums, int start, int end, int pivot) { + int low = start; + int high = end; + while (low <= high) { + while(low <= high && nums[low] < pivot) { + low++; + } + while(low <= high && nums[high] >= pivot) { + high--; + } + if (low <= high) { + swap(nums, low, high); + low++; + high--; + } + } + return low; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Partition List.java b/Others/old records/LintCode-Backup/Partition List.java new file mode 100644 index 0000000..5e4a1e1 --- /dev/null +++ b/Others/old records/LintCode-Backup/Partition List.java @@ -0,0 +1,81 @@ +不能像partitioin array一样从两边遍历。 + +那就最普通的,建造两个list + +把满足条件(=x)的数字分别放到两个list里面 + +记得用dummyNode track head. +最终pre.next = post链接起来。 +``` +/* +33% Accepted +Given a linked list and a value x, +partition it such that all nodes less than x come before nodes greater than or equal to x. + +You should preserve the original relative order of the nodes in each of the two partitions. + +For example, +Given 1->4->3->2->5->2->null and x = 3, +return 1->2->2->4->3->5->null. + +Example +Tags Expand +Linked List Two Pointers +*/ + +/* +Thinking process: +0. dummyPre, dummyPost to store the head of the 2 list +1. Append node.val < x to listPre +2. Append node.val >= x to listPost +3. Link them togeter +4. return dummyPre.next +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @param x: an integer + * @return: a ListNode + */ + public ListNode partition(ListNode head, int x) { + if (head == null) { + return head; + } + + ListNode dummyPre = new ListNode(0); + ListNode dummyPost = new ListNode(0); + ListNode pre = dummyPre; + ListNode post = dummyPost; + + while (head != null) { + if (head.val < x) { + pre.next = head; + pre = pre.next; + } else { + post.next = head; + post = post.next; + } + head = head.next; + } + + post.next = null; + pre.next = dummyPost.next; + + return dummyPre.next; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Permutation Index.java b/Others/old records/LintCode-Backup/Permutation Index.java new file mode 100644 index 0000000..0b67a44 --- /dev/null +++ b/Others/old records/LintCode-Backup/Permutation Index.java @@ -0,0 +1,89 @@ +这题目标为简单。但是做了很久。 +最后分析出来: +每个数位的数字,都是基于这个数字之前越过的战壕...好吧,意思是,跳过了多少种可能。 +对,就用4,2,1举例。网上大家都用这个例子。不行,我要换一个。 + +换【6,5,2】吧。我们找6,5,2是permudation里面的第几个。 +正常排序,也就是permutation的第一个,应该是【2,5,6】 +如果要从首位,2,变成6,要跨过多少条尸体呢? +很简单,高中就学过,重点来了:小于6的数字有多少个呢?(2,5).然后每个数字变成head,都有各自的变化可能,而每个数字打头,都有(n-1)!种可能。明显了吧,把每个(n-1)!加起来。 注意(n-1)意思就是出去开头的数字(2、5),后面有多少个,有序排列一下有多少情况,不就是(n-1)!嘛。 + 这一步,公式推出来就是很简单的 (有几个小于6的数字呀) ×(出去head剩下有多少个数字)! + +以上 种种,都是为了把6推上皇位,而牺牲的条数。 + +那么把6推上去以后,还有接下去的呢。 + +接下去要看5,2. +6确定,后面permudation可变的情况有可能是【6,5,2】,那还可能是【6,2,5】呢。 + +方法一样了。 +看given 数组的第二位5,算它接下去: +1. 有几个数字小于5呢? +2. 除去5,还有几个数字可以 factorial呢? +3. 一样的。第一步就结果乘以第二步。 + +接下去要看最后一个元素2了。 +一样的想法。 + + +6,5,2全看过了以后咋办。 +加起来呗。 +加起来,就是【6,5,2】上位,所踏过的所有小命啊! + +我这解释太生动了。因为耗费了好长时间思考... +``` +/* +Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1. + +Example +Given [1,2,4], return 1. +*/ + +/* + Thoughts: + Given some thoughts online: + Take one example 4,2,1 (totally reversed, worse case) + Assume array length = n + 1. If sorted, it should be 1,2,4. In permutation, when does 4 appear? It appears after 1xx,2xx. That is, it appears after all of the smaller ones show up. + 2. For each number smaller than 4 in later indexes, each of them all have (n-1)! mutations. n -1 is actaully: current 0-based index of 4. + Therefore, for head number 4, there are: + #ofSmallerNumber * (curr 0-base index)! + 3. For loop on each num, calculate + SUM {#ofSmallerNumber * (index i)!} + 4. To store #ofSmallerNum, put hashmap. For example, for number 4, with index 2: There are 2 numbers smaller than 4, which are 1 and 2. + + O(n^2) +*/ + +public class Solution { + + public long permutationIndex(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + HashMap map = new HashMap(); + int n = A.length; + long rst = 0; + //O(n^2) + //Count: in A, after A[i], how many smaller nums are left behind. + for (int i = 0; i < n; i++) { + int count = 0; + for (int j = i + 1; j < n; j++) { + if (A[j] < A[i]) { + count++; + } + } + map.put(A[i], count); + } + //O(n^2) + for (int i = 0; i < n; i++) { + long fact = 1; + for (int j = (n - i - 1); j >= 1; j--) { + fact *= j; + } + rst += map.get(A[i]) * fact; + } + return rst + 1; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Permutations II.java b/Others/old records/LintCode-Backup/Permutations II.java new file mode 100644 index 0000000..38a1438 --- /dev/null +++ b/Others/old records/LintCode-Backup/Permutations II.java @@ -0,0 +1,131 @@ +要unique,就是要确定visit过的那个index不被重新visit. +一个办法就是给一个visited queue。 和queue在所有的地方一同populate. 然后visited里面存得时visited indexes +``` +/* +Given a list of numbers with duplicate number in it. Find all unique permutations. + +Example +For numbers [1,2,2] the unique permutations are: + +[ + + [1,2,2], + + [2,1,2], + + [2,2,1] + +] + +Challenge +Do it without recursion. + +Tags Expand +LinkedIn Recursion + +*/ + + +/* + Thoughts: + Same as Permutation I, but check also check for duplicate, if duplicate, continue + Use a queue of marker to track if that index has been visited. +*/ +class Solution { + /** + * @param nums: A list of integers. + * @return: A list of unique permutations. + */ + public ArrayList> permuteUnique(ArrayList nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.size() == 0) { + return rst; + } + Queue> queue = new LinkedList>(); + Queue> visited = new LinkedList>(); + ArrayList list; + ArrayList mark; + for (int i = 0; i < nums.size(); i++) { + list = new ArrayList(); + list.add(nums.get(i)); + mark = new ArrayList(); + mark.add(i); + queue.offer(new ArrayList(list)); + visited.offer(new ArrayList(mark)); + } + + while (!queue.isEmpty()) { + list = queue.poll(); + mark = visited.poll(); + if (list.size() == nums.size()) { + if (!rst.contains(list)) { + rst.add(new ArrayList(list)); + } + continue; + } + for (int i = 0; i < nums.size(); i++) { + if (!mark.contains(i)) { + list.add(nums.get(i)); + mark.add(i); + queue.offer(new ArrayList(list)); + visited.offer(new ArrayList(mark)); + list.remove(list.size() - 1); + mark.remove(mark.size() - 1); + } + } + } + + return rst; + } +} + + + + +/* + +Thougths: +Use regular recursion, use a mark[] to make sure the same charactor at same postion won't be reused +Do a backtrack on the dfs, to make sure a element has same chance of 'selectd' or 'non-solectd' +*/ +class Solution { + /** + * @param nums: A list of integers. + * @return: A list of unique permutations. + */ + public ArrayList> permuteUnique(ArrayList nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.size() == 0) { + return rst; + } + Collections.sort(nums); + boolean[] mark = new boolean[nums.size()]; + dfs(nums, new ArrayList(), rst, mark); + return rst; + } + + public void dfs (ArrayList nums, ArrayList list, + ArrayList> rst, boolean[] mark) { + if (list.size() == nums.size()) { + rst.add(new ArrayList(list)); + return; + } + + for (int i = 0; i < nums.size(); i++) { + if (mark[i] || (i != 0 && mark[i - 1] && nums.get(i) == nums.get(i - 1))) { + continue; + } + list.add(nums.get(i)); + mark[i] = true; + dfs(nums, list, rst, mark); + list.remove(list.size() - 1); + mark[i] = false; + } + return; + } +} + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Permutations.java b/Others/old records/LintCode-Backup/Permutations.java new file mode 100644 index 0000000..89bfab2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Permutations.java @@ -0,0 +1,130 @@ +还是递归: 取,或者不取。 +Iterative: 用个queue,每次poll()出来的list, 把在nums里面能加的挨个加一遍。 +``` +/* +Given a list of numbers, return all possible permutations. + +Example +For nums [1,2,3], the permutaions are: + +[ + + [1,2,3], + + [1,3,2], + + [2,1,3], + + [2,3,1], + + [3,1,2], + + [3,2,1] + +] + +Challenge +Do it without recursion + +Tags Expand +Recursion Search + +*/ + +/* + Thoughts: 12.07.2015 recap + recursive: + pass list, rst, nums. + when list.size() == nums.size(), add to rst and return. + Need to re-add all of those non-added spots. So do for loop everytime to try all possible ways. + note: check if !list.contains(candiate). +*/ + +/* + 12.07.2015 + Now, do a non-recursive. + Set up a queue, add all elements into it. + give a size/level variable to keep track of cycle. + +*/ +class Solution { + /** + * @param nums: A list of integers. + * @return: A list of permutations. + */ + public ArrayList> permute(ArrayList nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.size() == 0) { + return rst; + } + Queue> queue = new LinkedList>(); + ArrayList list; + for (int num : nums) { + list = new ArrayList(); + list.add(num); + queue.offer(new ArrayList(list)); + } + + while (!queue.isEmpty()) { + list = queue.poll(); + if (list.size() == nums.size()) { + rst.add(new ArrayList(list)); + continue; + } + for (int i = 0; i < nums.size(); i++) { + if (!list.contains(nums.get(i))) { + list.add(nums.get(i)); + queue.offer(new ArrayList(list)); + list.remove(list.size() - 1); + } + } + } + + return rst; + } +} + + + +/* + +Thinking Process: +1. Very similar idea: choose or not choose (1 / 0) + A key point is: when jumpped into next level of recursion, the 'list' will surely be filled up until it reach the max length. + That is: when 'not choose', the empty seat will be filled eventually with points not existed in 'list'. +2. The recursion does not end before the list is filled. +3. A for loop is doiong the filling of blank. Any order/combination will occur. +*/ + +class Solution { + /** + * @param nums: A list of integers. + * @return: A list of permutations. + */ + public ArrayList> permute(ArrayList nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.size() == 0) { + return rst; + } + ArrayList list = new ArrayList(); + helper(rst, list, nums); + return rst; + } + + public void helper(ArrayList> rst, ArrayList list, ArrayList nums) { + if (list.size() == nums.size()) { + rst.add(new ArrayList(list)); + return ; + } + for (int i = 0; i < nums.size(); i++) { + if (!list.contains(nums.get(i))) { + list.add(nums.get(i)); + helper(rst, list, nums); + list.remove(list.size() - 1); + } + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Plus One.java b/Others/old records/LintCode-Backup/Plus One.java new file mode 100644 index 0000000..4659f19 --- /dev/null +++ b/Others/old records/LintCode-Backup/Plus One.java @@ -0,0 +1,95 @@ +/* +Given a non-negative number represented as an array of digits, plus one to the number. + +The digits are stored such that the most significant digit is at the head of the list. + + +Example +Given [1,2,3] which represents 123, return [1,2,4]. + +Given [9,9,9] which represents 999, return [1,0,0,0]. + +Tags Expand +Array + +*/ + +public class Solution { + public int[] plusOne(int[] digits) { + if(digits.length==0) return digits; + + digits[digits.length-1] += 1; + //Check index digit.length-1 to 1 + for(int i = digits.length-1; i>0; i--){ + if(digits[i] == 10){ + digits[i]=0; + digits[i-1]+=1; + } + else return digits; + } + + //Check index 0. If ==0, set it to 0 and carry over 1 + if(digits[0]==10){ + int[] output = new int[digits.length+1]; + output[0] = 1; + output[1] = 0; + for(int i=2; i= 0) { + return pow(x, n); + } else { + return 1/pow(x, n); + } + } + + public double pow(double x, int n) { + if (n == 0) { + return 1; + } + double num = pow(x, n/2); + if (n % 2 == 0) { + return num * num; + } + return num * num * x; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Product of Array Exclude Itself.java b/Others/old records/LintCode-Backup/Product of Array Exclude Itself.java new file mode 100644 index 0000000..2eb4432 --- /dev/null +++ b/Others/old records/LintCode-Backup/Product of Array Exclude Itself.java @@ -0,0 +1,44 @@ +/* +Given an integers array A. + +Define B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], calculate B WITHOUT divide operation. + +Example +For A = [1, 2, 3], return [6, 3, 2]. + +Tags Expand +Forward-Backward Traversal LintCode Copyright + +Thought: +Trivial way would be first calculate the zigma(A[0]* ... A[n-1]) then divide by B[i]. However, not allowed in this question. + +The other way: do for loop again and again? that will be n^2 time. + +*/ + + + +public class Solution { + /** + * @param A: Given an integers array A + * @return: A Long array B and B[i]= A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1] + */ + public ArrayList productExcludeItself(ArrayList A) { + if (A == null || A.size() == 0) { + return null; + } + ArrayList rst = new ArrayList(); + for (int i = 0; i < A.size(); i++) { + long num = 1; + for (int j = 0; j < A.size(); j++) { + if (j != i) { + num *= A.get(j); + } + } + rst.add(num); + } + return rst; + } +} + + diff --git a/Others/old records/LintCode-Backup/QuickSort.java b/Others/old records/LintCode-Backup/QuickSort.java new file mode 100644 index 0000000..9f1a879 --- /dev/null +++ b/Others/old records/LintCode-Backup/QuickSort.java @@ -0,0 +1,64 @@ +代码是不难的. + +首先partition. 返还一个partition的那个中间点的位置。 +然后劈开两半。 +前后各自 quick sort, recursively + +注意:在partition里面, 比较的时候nums[start] < pivot, nums[end]>pivot, 如果写成了 <= 会 stack overflow. + + +但是: 在partition array那个题目里面,第二个 nums[end] >= pivot, 是要去加上这个 ‘=’的 +``` +/* +Quick Sort a array. + +Self test. + +*/ + +class Solution{ + public void quickSort(int[] nums){ + if (nums == null || nums.length == 0) { + return; + } + sortHelper(nums, 0, nums.length - 1); + } + + public void sortHelper(int[] nums, int start, int end){ + if (start >= end) { + return; + } else { + + int partitionPoint = partition(nums, start, end); + sortHelper(nums, start, partitionPoint - 1); + sortHelper(nums, partitionPoint, end); + } + } + + public void swap(int[] nums, int x, int y) { + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } + + public int partition(int[] nums, int start, int end){ + int mid = start + (end - start)/2; + + int pivot = nums[mid]; + while (start <= end) { + while (start <= end && nums[start] < pivot) { + start++; + } + while (start <= end && nums[end] > pivot) { + end--; + } + if (start <= end) { + swap(nums, start, end); + start++; + end--; + } + } + return start; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Recover Rotated Sorted Array.java b/Others/old records/LintCode-Backup/Recover Rotated Sorted Array.java new file mode 100644 index 0000000..67030ac --- /dev/null +++ b/Others/old records/LintCode-Backup/Recover Rotated Sorted Array.java @@ -0,0 +1,73 @@ +rotate的意思,是有个点断开,把一边的array节选出来放在另外一边。 +Rotate三步: +rotate前半 +rotate后半 +rotate全部 + +注意先找到断点。 +``` +/* +Given a rotated sorted array, recover it to sorted array in-place. + +Example +[4, 5, 1, 2, 3] -> [1, 2, 3, 4, 5] + +Challenge +In-place, O(1) extra space and O(n) time. + +Clarification +What is rotated array: + + - For example, the orginal array is [1,2,3,4], The rotated array of it can be [1,2,3,4], [2,3,4,1], [3,4,1,2], [4,1,2,3] + +Tags Expand +Array Sorted Array + + +*/ + +/* + Thougths: 12.08.2015. + Same idea as previous solution. Just re-write to practice + 1. reverse function. + 2. find break point. + 3. reverse! + - reverse 1st part + - reverse 2nd part + - reverse all +*/ +public class Solution { + public void recoverRotatedSortedArray(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return; + } + for (int i = 0; i < nums.size() - 1; i++) { + if (nums.get(i) > nums.get(i + 1)) { + reverse(nums, 0, i); + reverse(nums, i + 1, nums.size() - 1); + reverse(nums, 0, nums.size() - 1); + return; + } + } + + } + //reverse certain range + public void reverse(ArrayList nums, int start, int end){ + for (int i = start, j = end; i < j; i++,j--) { + int temp = nums.get(i); + nums.set(i, nums.get(j)); + nums.set(j, temp); + } + } +} + +/* +Thinking process: + Create a reverse function + When there is a wrong position, start 3 steps: + 1. Reverse 1st part. + 2. Reverse 2nd part. + 3. Reverse them all. +*/ + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Rehashing.java b/Others/old records/LintCode-Backup/Rehashing.java new file mode 100644 index 0000000..37f69b4 --- /dev/null +++ b/Others/old records/LintCode-Backup/Rehashing.java @@ -0,0 +1,126 @@ +/* +The size of the hash table is not determinate at the very beginning. If the total size of keys is too large (e.g. size >= capacity / 10), we should double the size of the hash table and rehash every keys. Say you have a hash table looks like below: + +size=3, capacity=4 + +[null, 21, 14, null] + ↓ ↓ + 9 null + ↓ + null +The hash function is: + +int hashcode(int key, int capacity) { + return key % capacity; +} +here we have three numbers, 9, 14 and 21, where 21 and 9 share the same position as they all have the same hashcode 1 (21 % 4 = 9 % 4 = 1). We store them in the hash table by linked list. + +rehashing this hash table, double the capacity, you will get: + +size=3, capacity=8 + +index: 0 1 2 3 4 5 6 7 +hash : [null, 9, null, null, null, 21, 14, null] +Given the original hash table, return the new hash table after rehashing . + +Example +Given [null, 21->9->null, 14->null, null], + +return [null, 9->null, null, null, null, 21->null, 14->null, null] + +Note +For negative integer in hash table, the position can be calculated as follow: + +C++/Java: if you directly calculate -4 % 3 you will get -1. You can use function: a % b = (a % b + b) % b to make it is a non negative integer. +Python: you can directly use -1 % 3, you will get 2 automatically. +Tags Expand +LintCode Copyright Hash Table + +Thoughts: +1. Loop through the hashtable[] and find longest, calcualte new capacity +2. rehash + +*/ + +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + public class Solution { + /** + * @param hashTable: A list of The first node of linked list + * @return: A list of The first node of linked list which have twice size + */ + public ListNode[] rehashing(ListNode[] hashTable) { + if (hashTable == null || hashTable.length == 0) { + return hashTable; + } + //Find longest size + /* + int longest = 0; + for (int i = 0; i < hashTable.length; i++) { + ListNode node = hashTable[i]; + int count = 0; + while (node != null) { + count++; + node = node.next; + } + longest = Math.max(longest, count); + }*/ + //Calculate new capacity + //Just to clarify, this problem asks to double the hashtable size, rather than 'longest' times longer. + int capacity = hashTable.length * 2; + if (capacity == hashTable.length) { + return hashTable; + } + + ListNode[] rst = new ListNode[capacity]; + for (int i = 0; i < hashTable.length; i++) { + ListNode node = hashTable[i]; + while (node != null) { + ListNode newNode = new ListNode(node.val); + int hCode = hashcode(newNode.val, capacity); + if (rst[hCode] == null) { + rst[hCode] = newNode; + } else { + ListNode move = rst[hCode]; + while (move.next != null) { + move = move.next; + } + move.next = newNode; + } + node = node.next; + } + } + + return rst; + } + + public int hashcode(int key, int capacity) { + if (key < 0) { + return (key % capacity + capacity) % capacity; + } else { + return key % capacity; + } + } +}; + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Remove Duplicates from Sorted Array.java b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted Array.java new file mode 100644 index 0000000..48c960c --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted Array.java @@ -0,0 +1,60 @@ +Remove Duplicate from Array 不同于remove from linked list. + +LinkedList里面我们是最好不要动node.val的,直接把node去掉。 +而array我们很难直接把node去掉,又不能用新array,那么就要: + +把不重复的element一个个放到最前面。 + + +这个思想跟merge two sorted array (其中一个后续非常长的array可以放下arr1,arr2) 类似。 +就是找个不会事后mess up,不会去动得index,把满足条件的element 填进去。这样保证了in place. + +* 有个反向思维:remove duplicate,实际上也是找unique elements, and insert into original array + +``` +/*31% Accepted +Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. + +Do not allocate extra space for another array, you must do this in place with constant memory. + +For example, +Given input array A = [1,1,2], + +Your function should return length = 2, and A is now [1,2]. + +Example +Tags Expand +Array Two Pointers + +Thinking Process: +Two pointers, i, j +i: the regular for loop +j - jumper: +If nums[i] == nums[j], do not update nums[j]. It stays the same. +after i++, compare nums[j] with the new nums[i]. If not the same, means the position after j can have a new number that’s not duplicate of nums[j]. In this case, we update nums[j] = nums[i]. +Do this until regular i runs out. +At the end, j is actually the last index of new Array. j + 1 is the size. +*/ + +public class Solution { + /** + * @param A: a array of integers + * @return : return an integer + */ + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int i = 0; + int j = 0; + for (i = 0; i < nums.length; i++) { + if (nums[j] != nums[i]) { + nums[++j] = nums[i]; + } + } + return j + 1; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List II.java b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List II.java new file mode 100644 index 0000000..5da207e --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List II.java @@ -0,0 +1,65 @@ +斩草除根。 +多个node,check node.next ?= node.next.next +``` +/* +26% Accepted +Given a sorted linked list, delete all nodes that have duplicate numbers, +leaving only distinct numbers from the original list. + +Example +Given 1->2->3->3->4->4->5, return 1->2->5. +Given 1->1->1->2->3, return 2->3. + +Tags Expand +Linked List + +Thinking process: +Create a dummyHead +User a pointer node to run through the list +Similar to Remove Duplicates from Sorted List I, but checking next and next.next +If there is a match on head.next && head.next.next, delete head.next node and link to next ones until a different node appear +return dummyHead.next +*/ + + +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param ListNode head is the head of the linked list + * @return: ListNode head of the linked list + */ + public static ListNode deleteDuplicates(ListNode head) { + if (head == null) { + return head; + } + ListNode dummyHead = new ListNode(0); + dummyHead.next = head; + ListNode node = dummyHead; + + while (node.next != null && node.next.next != null) { + if (node.next.val == node.next.next.val) { + int duplicatedVal = node.next.val; + while (node.next != null && node.next.val == duplicatedVal) { + node.next = node.next.next; + } + } else { + node = node.next; + } + } + + return dummyHead.next; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List.java b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List.java new file mode 100644 index 0000000..5815642 --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Duplicates from Sorted List.java @@ -0,0 +1,63 @@ +一旦node.next 和node是重复,跳 +``` +/* +40% 通过 +Given a sorted linked list, delete all duplicates such that each element appear only once. + +样例 +Given 1->1->2, return 1->2. +Given 1->1->2->3->3, return 1->2->3. + +标签 Expand +Linked List + +Thinking process: +check head null +Use dummy node to reserve head +while everything when head.next is not null +compare head.val == head.next.val? +If so, head.next = head.next.next +*/ + +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param ListNode head is the head of the linked list + * @return: ListNode head of linked list + */ + public static ListNode deleteDuplicates(ListNode head) { + if (head == null) { + return head; + } + ListNode node = head; + while (node.next != null) { + if (node.val == node.next.val) { + node.next = node.next.next; + } else { + node = node.next; + } + } + return head; + } +} + + + + +/* +Use two pointers: +http://gongxuns.blogspot.com/2012/12/leetcode-remove-duplicates-from-sorted_11.html +*/ + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Remove Duplicates from Unsorted List.java b/Others/old records/LintCode-Backup/Remove Duplicates from Unsorted List.java new file mode 100644 index 0000000..1600519 --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Duplicates from Unsorted List.java @@ -0,0 +1,155 @@ +基本方法: O(n) sapce, time +遍历。 +遇到duplicate(可能多个), while直到node.next不是duplicate. +接下去,既然不是duplicate,那就add 进 set + + +如果不用extra memory, do it in place: +那就要sort linked list. 用merge sort. + +复习merge sort: +1. find middle. +2. recursively: right = sort(mid.next); left = sort(head). +3. within sort(), at the end call merge(left, right) +``` +/* +Remove Duplicates from Unsorted List + +Write code to remove duplicates from an unsorted linked list. + +Example +Given 1->3->2->1->4. + +Return 1->3->2->4 + +Challenge +(hard) How would you solve this problem if a temporary buffer is not allowed? In this case, you don't need to keep the order of nodes. +Tags Expand +Linked List +*/ + +/* + Thoughts: + Basic: use a hashSet to store node. Skip duplicate +*/ +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ + +public class Solution { + /** + * @param head: The first node of linked list. + * @return: head node + */ + public ListNode removeDuplicates(ListNode head) { + if (head == null) { + return head; + } + HashSet set = new HashSet(); + ListNode node = head; + set.add(node.val); + while (node != null) { + while (node.next != null && set.contains(node.next.val)) { + node.next = node.next.next; + } + if (node.next != null) { + set.add(node.next.val); + } + node = node.next; + } + return head; + } +} + + +//No extra buffer: merge Sort the linked list, then loop it through + +public class Solution { + /** + * @param head: The first node of linked list. + * @return: head node + */ + public ListNode removeDuplicates(ListNode head) { + if (head == null) { + return head; + } + ListNode newHead = sort(head); + ListNode dummy = newHead; + while (newHead != null) { + if (newHead.next != null && newHead.val == newHead.next.val) { + newHead.next = newHead.next.next; + } + newHead = newHead.next; + } + return dummy; + } + //Merge Sort's code + + /* + Merge sort, using findMidle and merge. + */ + public ListNode sort(ListNode node) { + if (node == null || node.next == null) { + return node; + } + ListNode mid = findMiddle(node); + ListNode right = sort(mid.next); + mid.next = null; + ListNode left = sort(node); + return merge(left, right); + } + + + /* + Two pointer slow, fast + When fast pointer reaches end, return mid; + */ + public ListNode findMiddle(ListNode node){ + ListNode slow = node; + ListNode fast = node.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + /* + Merge the two list based on value + */ + public ListNode merge(ListNode n1, ListNode n2) { + ListNode node = new ListNode(0); + ListNode dummy = node; + while (n1 != null && n2 != null) { + if (n1.val < n2.val) { + node.next = n1; + n1 = n1.next; + } else { + node.next = n2; + n2 = n2.next; + } + node = node.next; + } + if (n1 != null) { + node.next = n1; + } + if (n2 != null) { + node.next = n2; + } + return dummy.next; + } + + +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Remove Linked List Elements.java b/Others/old records/LintCode-Backup/Remove Linked List Elements.java new file mode 100644 index 0000000..b5aaad8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Linked List Elements.java @@ -0,0 +1,54 @@ +如果match. parent.next = node.next. +如果不match, parent 和 node 一起移动 +``` +/* +Remove all elements from a linked list of integers that have value val. + +Have you met this question in a real interview? Yes +Example +Given 1->2->3->3->4->5->3, val = 3, you should return the list as 1->2->4->5 + +Tags Expand +Linked List +*/ + +/* +Thoughts: +While loop through. Maintain a parent, so it can be used to skip current node. +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + /** + * @param head a ListNode + * @param val an integer + * @return a ListNode + */ + public ListNode removeElements(ListNode head, int val) { + if (head == null) { + return head; + } + ListNode parent = new ListNode(0); + parent.next = head; + ListNode dummy = parent; + while (head != null) { + if (head.val == val) { + parent.next = head.next; + } else { + parent = parent.next; + } + head = head.next; + } + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Remove Node in Binary Search Tree.java b/Others/old records/LintCode-Backup/Remove Node in Binary Search Tree.java new file mode 100644 index 0000000..bffbc98 --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Node in Binary Search Tree.java @@ -0,0 +1,135 @@ +/* +Given a root of Binary Search Tree with unique value for each node. Remove the node with given value. If there is no such a node with given value in the binary search tree, do nothing. You should keep the tree still a binary search tree after removal. + +Example +Given binary search tree: + + 5 + + / \ + + 3 6 + + / \ + +2 4 + +Remove 3, you can either return: + + 5 + + / \ + + 2 6 + + \ + + 4 + +or : + + 5 + + / \ + + 4 6 + + / + +2 + +Tags Expand +LintCode Copyright Binary Search Tree + +Thoughts: +We can think of a couple different cases: where is that target node to remove? It can be root, a child (a couple more situations) +Note: before going futher, remember the technique to rip off parent node. In a binary tree, L > parent > R, so always find the L's right-most node and replace parent. +Cases1: +0. Root is target: find L's right-most node, replace root. +case1. A node with 2 null children: set target.parent.L/R = null +case2. A node with just just left node: set target.parent.L/R = target.right +case3. A node with left ndoe != null: find target.right-most node's left side X and replace target.parent.L/R.value = X.value. Remove set that X to null. + +Divide into 2 major task: +1. Find the target node, and it's parent. +2. Remove that node (most complex logic) +*/ +public class Solution { + public TreeNode removeNode(TreeNode root, int value) { + if (root == null || (root.left == null && root.right == null)) { + return null; + } + TreeNode dummy = new TreeNode(0);; + dummy.left = root; + //Find node + TreeNode parent = findTargetParent(dummy, root, value); + TreeNode child; + if (parent.left != null && parent.left.val == value) { + child = parent.left; + } else if (parent.right != null && parent.right.val == value) { + child = parent.right; + } else { + return dummy.left; + } + //Delete that node: + deleteTargetNode(parent, child); + return dummy.left; + } + + + //Find target node + public TreeNode findTargetParent(TreeNode parent, TreeNode node, int value){ + if (node == null || node.val == value) { + return parent; + } + + if (value < node.val) { + return findTargetParent(node, node.left, value); + } else { + return findTargetParent(node, node.right, value); + } + } + //Delete node + public void deleteTargetNode(TreeNode parent, TreeNode target) { + //Case1 + case2: (target.L == null && target.R == null) || (target.R == null && target.L != null) + if (target.right == null) { + if (parent.left == target) { + parent.left = target.left; + } else { + parent.right = target.left; + } + } else {//Case3: when target.right != null + TreeNode replaceNode = target.right; + TreeNode replaceParent = target; + while(replaceNode.left != null) { + replaceParent = replaceNode; + replaceNode = replaceNode.left; + } + //Remove replaceNode from replaceParent + if (replaceParent.left == replaceNode) {//Usually it'll be replaceParent.left + replaceParent.left = replaceNode.right; + } else {//Sometimes when target.left == null, than means replaceParent.right will be replaceNode (while loop didn't start at all) + replaceParent.right = replaceNode.right; + } + + //Remove target from parent: not sure it's left or right node of parent + if (parent.left == target) { + parent.left = replaceNode; + } else { + parent.right = replaceNode; + } + + replaceNode.left = target.left; + replaceNode.right = target.right; + } + } + +} + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Remove Nth Node From End of List.java b/Others/old records/LintCode-Backup/Remove Nth Node From End of List.java new file mode 100644 index 0000000..cc8a57a --- /dev/null +++ b/Others/old records/LintCode-Backup/Remove Nth Node From End of List.java @@ -0,0 +1,62 @@ +/* +Given a linked list, remove the nth node from the end of list and return its head. + +Note +The minimum number of nodes in list is n. + +Example +Given linked list: 1->2->3->4->5->null, and n = 2. +After removing the second node from the end, the linked list becomes 1->2->3->5->null. +Challenge +O(n) time + +Tags Expand +Two Pointers Linked List + +Thinking process: +Very similar to 'Nth to last node'. Except, have a pre pointer to keep track of the previous node of 'nth to last'. +Also have a dummy.next to store the beginning of the list; +*/ +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @param n: An integer. + * @return: The head of linked list. + */ + ListNode removeNthFromEnd(ListNode head, int n) { + if (head == null || n < 0) { + return null; + } + int count = 0; + ListNode dummy = new ListNode(0); + ListNode pre = new ListNode(0); + pre.next = head; + dummy = pre; + ListNode node = head; + while (node != null && count < n) { + node = node.next; + count++; + } + while (node != null) { + node = node.next; + head = head.next; + pre = pre.next; + } + pre.next = head.next; + return dummy.next; + } +} + + + diff --git a/Others/old records/LintCode-Backup/Reorder List.java b/Others/old records/LintCode-Backup/Reorder List.java new file mode 100644 index 0000000..ada5af2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Reorder List.java @@ -0,0 +1,93 @@ +/* +24% 通过 +Given a singly linked list L: L0→L1→…→Ln-1→Ln, +reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… + +You must do this in-place without altering the nodes' values. + + + +样例 +For example, +Given 1->2->3->4->null, reorder it to 1->4->2->3->null. + +标签 Expand +Linked List + +Thinking Process: +Similar to sort list: +find middle. +reverse last section +merge(head, mid) alternatively by using index % 2. +Append whatever left from the 2 lists +Note: re-order in place, does not necessarily mean you can create any variable. As long as the variable is O(1), it should be fine. +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + private ListNode reverse(ListNode head) { + ListNode reversedList = null; + while (head != null) { + ListNode temp = head.next; + head.next = reversedList; + reversedList = head; + head = temp; + } + return reversedList; + } + + private void merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + int index = 0; + while (head1 != null && head2 != null) { + if (index % 2 == 0) { + dummy.next = head1; + head1 = head1.next; + } else { + dummy.next = head2; + head2 = head2.next; + } + dummy = dummy.next; + index += 1; + } + if (head1 != null) { + dummy.next = head1; + } else if (head2 != null) { + dummy.next = head2; + } + } + + private ListNode findMiddle(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + + public void reorderList(ListNode head) { + if (head == null || head.next == null) { + return; + } + + ListNode mid = findMiddle(head); + ListNode tail = reverse(mid.next); + mid.next = null; + + merge(head, tail); + } +} + diff --git a/Others/old records/LintCode-Backup/Reverse Integer.java b/Others/old records/LintCode-Backup/Reverse Integer.java new file mode 100644 index 0000000..37c51bc --- /dev/null +++ b/Others/old records/LintCode-Backup/Reverse Integer.java @@ -0,0 +1,37 @@ +/* +Reverse digits of an integer. Returns 0 when the reversed integer overflows (signed 32-bit integer). + +Example +Given x = 123, return 321 + +Given x = -123, return -321 + +Tags Expand +Integer + +Thoughts: +1. Use long to capture the result. If > Integer.MAX_VALUE,return 0; +2. Use string to reverse, the conver to long +3. use string builder to reverse string + +*/ + + +public class Solution { + /** + * @param n the integer to be reversed + * @return the reversed integer + */ + public int reverseInteger(int n) { + long num = (long)n; + int sign = n > 0 ? 1 : -1; + String rst = new StringBuilder(Math.abs(num)+"").reverse().toString(); + num = Long.parseLong(rst) * sign; + + if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE) { + return 0; + } else { + return (int)num; + } + } +} diff --git a/Others/old records/LintCode-Backup/Reverse Linked List II .java b/Others/old records/LintCode-Backup/Reverse Linked List II .java new file mode 100644 index 0000000..6a75f48 --- /dev/null +++ b/Others/old records/LintCode-Backup/Reverse Linked List II .java @@ -0,0 +1,88 @@ +遍历到M前, +存一下那个点, +从M开始, for loop, reverse [m~n]。 然后把三段链接在一起。 + + +``` +/* +28% Accepted +Reverse a linked list from position m to n. + +Note +Given m, n satisfy the following condition: 1 = m = n = length of list. + +Example +Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. + +Challenge +Reverse it in-place and in one-pass + +Tags Expand +Linked List + +Thinking process: +0. Use dummy node to store head +1. Find mNode, store the front nodes +2. Reverse from mNode to nNode +3. Link front, middle, end nodes together +Note, when doing reverse, always: + - reversedList = 1st item + - postNode = 2nd item + - store 3rd item in temp: temp = postNode.next +*/ + +/** + * Definition for ListNode + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param ListNode head is the head of the linked list + * @oaram m and n + * @return: The head of the reversed ListNode + */ + public ListNode reverseBetween(ListNode head, int m, int n) { + if (head == null || m >= n) { + return head; + } + + ListNode dummyNode = new ListNode(0); + dummyNode.next = head; + head = dummyNode; + ListNode nodeFront = null; + + + for (int countM = 1; countM < m; countM++) { + if (head == null) { + return head; + } + head = head.next; + } + nodeFront = head; + ListNode mNode = head.next; //Head is Mth node. Reserve it + ListNode reversedList = mNode; + ListNode postNode = mNode.next; + for (int countN = m; countN < n; countN++) { + ListNode temp = postNode.next; + postNode.next = reversedList; + reversedList = postNode; + postNode = temp; + } + //List front, middle and end section + nodeFront.next = reversedList; + mNode.next = postNode; + + return dummyNode.next; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Reverse Linked List.java b/Others/old records/LintCode-Backup/Reverse Linked List.java new file mode 100644 index 0000000..174b727 --- /dev/null +++ b/Others/old records/LintCode-Backup/Reverse Linked List.java @@ -0,0 +1,38 @@ +E + +建立新list。每次把newList append 在current node的后面。 +用head来循环所有node。 + +``` +/* +Reverse a linked list. + +Have you met this question in a real interview? Yes +Example +For linked list 1->2->3, the reversed linked list is 3->2->1 + +Challenge +Reverse it in-place and in one-pass + +Tags Expand +Linked List Facebook Uber +*/ + +//Use empty node, add to tail, append empty node to next node. keep going like that +public class Solution { + public ListNode reverseList(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode newList = null; + + while (head != null) { + ListNode temp = head.next; + head.next = newList; + newList = head; + head = temp; + } + return newList; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Reverse Words in a String.java b/Others/old records/LintCode-Backup/Reverse Words in a String.java new file mode 100644 index 0000000..934ef0b --- /dev/null +++ b/Others/old records/LintCode-Backup/Reverse Words in a String.java @@ -0,0 +1,145 @@ +几种不同的方法flip: +坑: 1. 结尾不能有空格。 2. 注意,如果Input是 ‘ ’的话,split以后就啥也没有了。check split以后 length == 0 +``` +/* +23% Accepted +Given an input string, reverse the string word by word. + +For example, +Given s = "the sky is blue", +return "blue is sky the". + +Example +Clarification +What constitutes a word? +A sequence of non-space characters constitutes a word. + +Could the input string contain leading or trailing spaces? +Yes. However, your reversed string should not contain leading or trailing spaces. +How about multiple spaces between two words? +Reduce them to a single space in the reversed string. +Tags Expand +String +*/ + + + + + +/* + Thoughts:12.08.2015 + Have multiple two other ways to do it: + 1. flip all,then flip each individual word; + 2. break into parts and append from end to beginning. + For simplicity of code, try the appending from behind. +*/ +public class Solution { + public String reverseWords(String s) { + if (s == null || s.length() == 0 || s.indexOf(" ") == -1) { + return s; + } + + String[] strs = s.split(" "); + if (strs.length == 0) { + return s; + } + StringBuffer sb = new StringBuffer(); + + for (int i = strs.length - 1; i >= 0; i--) { + sb.append(strs[i] + " "); + } + + return sb.substring(0, sb.length() - 1).toString(); + } +} + + + + +/* +Thinking Process: +1. Reverse it like reversing a int array +2. Use Split into arrays. +3. When reversing, make sure not empty string "" +*/ +public class Solution { + /** + * @param s : A string + * @return : A string + */ + public String reverseWords(String s) { + String[] strs = s.split(" "); + for (int i = 0, j = strs.length - 1; i < j; i++, j--) { + String temp = new String(strs[j]); + strs[j] = new String(strs[i]); + strs[i] = temp; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < strs.length; i++){ + if (strs[i].length() > 0) { + sb.append(strs[i]); + if (i < strs.length - 1) { + sb.append(" "); + } + } + } + return sb.toString(); + } +} + + +/* + + Thoughts: 12.08.2015, + Try the reverse method on string + This is the leaset favor: because it creates too much trouble. + Simply reverse the words broken into String[] with split(" ") is much easier + + Only good practice here: the reverse with StringBuffer +*/ + // I LOVE YOU +public class Solution { + public String reverseWords(String s) { + //Reverse the contents of the string buffer + public void reverse(StringBuffer sb, int start, int end) { + for (int i = start, j = end; i < j; i++,j--) { + char temp = sb.charAt(i); + sb.setCharAt(i, sb.charAt(j)); + sb.setCharAt(j, temp); + } + } + + if (s == null || s.length() == 0 || s.indexOf(" ") == -1) { + return s; + } + s = s.trim();//no head && tail " " + if (s.length() == 0) { + return s; + } + + StringBuffer sb = new StringBuffer(); + for (String str : s.split(" ")) { + if (str.trim().length() != 0) { + sb.append(str + " "); + } + } + + reverse(sb, 0, sb.length() - 1); + sb.append(" "); + int start = 1; + int end = start + sb.substring(start).indexOf(" "); + //Process all words separate by space + while (end != -1 && start < end) { + reverse(sb, start, end - 1); + start = end + 1; + end = start + (sb.substring(start)).indexOf(" "); + } + + return sb.toString().trim(); + } + + + +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Rotate Image.java b/Others/old records/LintCode-Backup/Rotate Image.java new file mode 100644 index 0000000..c832148 --- /dev/null +++ b/Others/old records/LintCode-Backup/Rotate Image.java @@ -0,0 +1,51 @@ +M + +找到个转角度的规律公式。用一个temp。in place. + +``` +/* +You are given an n x n 2D matrix representing an image. +Rotate the image by 90 degrees (clockwise). + +Have you met this question in a real interview? Yes +Example +Given a matrix + +[ + [1,2], + [3,4] +] +rotate it by 90 degrees (clockwise), return + +[ + [3,1], + [4,2] +] +Challenge +Do it in-place. + +Tags Expand +Cracking The Coding Interview Matrix +*/ + + +//in matrix, to find next position: r = c; c = (w - r). Work on the equation => oldR = w - c, oldC = r +//In pace: do loop, change 4 at once. do a quater of the matrix +public class Solution { + public void rotate(int[][] matrix) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return; + } + int width = matrix.length; + for (int i = 0; i < width/2; i++) { + for (int j = 0; j < Math.ceil(width/2.0); j++) { + int temp = matrix[i][j]; + matrix[i][j] = matrix[width - 1 - j][i]; + matrix[width - 1 - j][i] = matrix[width - 1 - i][width - 1 - j]; + matrix[width - 1 - i][width - 1 - j] = matrix[j][width - 1 - i]; + matrix[j][width - 1 - i] = temp; + } + } + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Rotate List.java b/Others/old records/LintCode-Backup/Rotate List.java new file mode 100644 index 0000000..7c64d9f --- /dev/null +++ b/Others/old records/LintCode-Backup/Rotate List.java @@ -0,0 +1,64 @@ + +/* Given a list, rotate the list to the right by k places, where k is non-negative. + +Example +Given 1->2->3->4->5->null and k=2 +return 4->5->1->2->3->null +Tags Expand +Basic Implementation Linked List + +Thining process: +Two pointers. +First pointer move k steps. +Then 2 pointers start moving together. When 1st pointer reaches the end, then 2nd pointer should be in middle. +Let 2nd pointer be head, and move original head to tail of the list + +*/ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param head: the List + * @param k: rotate to the right k places + * @return: the list after rotation + */ + public ListNode rotateRight(ListNode head, int k) { + if (head == null || k == 0) { + return head; + } + //Check length + int length = 0; + ListNode dummy = head; + while(dummy != null) { + dummy = dummy.next; + length++; + } + k = k % length; + //Store dummy as 1 node before tail + dummy = new ListNode(0); + dummy.next = head; + head = dummy; + for (int i = 0; i < k; i++) { + head = head.next; + } + //Move 2 pointers. When head reaches end, tail.next will be at the newHead + ListNode tail = dummy; + while (head.next != null) { + head = head.next; + tail = tail.next; + } + head.next = dummy.next;//Link old Head to the end, form circle + dummy.next = tail.next;//Link tail.next as new head. tail should be end point. + tail.next = null;//add null to end point tail + return dummy.next; + } +} diff --git a/Others/old records/LintCode-Backup/Rotate String.java b/Others/old records/LintCode-Backup/Rotate String.java new file mode 100644 index 0000000..b1840f9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Rotate String.java @@ -0,0 +1,54 @@ +还是三步rotate. +有个坑:offset可能很长,那么要%length,才能得到真正需要rotate的部分。 +Note: rotate 一个 full length之后,是string 不变 +``` +/* +17% Accepted +Given a string and an offset, rotate string by offset. (rotate from left to right) + +Example +Given "abcdefg" + +for offset=0, return "abcdefg" + +for offset=1, return "gabcdef" + +for offset=2, return "fgabcde" + +for offset=3, return "efgabcd" + +... + + +Tags Expand +String +*/ + +public class Solution { + /* + * param A: A string + * param offset: Rotate string with offset. + * return: Rotated string. + */ + public char[] rotateString(char[] A, int offset) { + if (A == null || A.length == 0) return A; + offset = offset % (A.length); + reverse(A, 0, A.length - offset - 1); + reverse(A, A.length - offset, A.length - 1); + reverse(A, 0, A.length - 1); + return A; + } + + + //Helper function: reverse certain range of array + public void reverse(char[] A, int start, int end) { + for (int i = start, j = end; i < j; i++, j--) { + char temp = A[j]; + A[j] = A[i]; + A[i] = temp; + } + } +}; + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search Insert Position.java b/Others/old records/LintCode-Backup/Search Insert Position.java new file mode 100644 index 0000000..c259195 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search Insert Position.java @@ -0,0 +1,104 @@ +一般的binary search. +在结尾判断该return 哪个position。 +``` +/* +28% Accepted +Given a sorted array and a target value, return the index if the target is found. +If not, return the index where it would be if it were inserted in order. + +You may assume no duplicates in the array. + +Example +[1,3,5,6], 5 → 2 +[1,3,5,6], 2 → 1 +[1,3,5,6], 7 → 4 +[1,3,5,6], 0 → 0 + +Tags Expand +Binary Search Array Sorted Array +*/ + +/* + Recap 12.08.2015 + Find the occurance of the target, return it. + If not found, at the point, start + 1 = end + return the insert position at start + 1 +*/ + +public class Solution { + + public int searchInsert(int[] A, int target) { + if (A == null || A.length == 0) {//Insert at 0 position + return 0; + } + int start = 0; + int end = A.length - 1; + int mid = start + (end - start)/2; + + while (start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + return mid; + } else if (A[mid] > target) { + end = mid; + } else { + start = mid; + } + } + + if (A[start] >= target) { + return start; + } else if (A[start] < target && target <= A[end]) { + return end; + } else { + return end + 1; + } + } +} + + + + +//older version +public class Solution { + /** + * param A : an integer sorted array + * param target : an integer to be inserted + * return : an integer + */ + public int searchInsert(ArrayList A, int target) { + // write your code here + int start = 0; + int end = A.size() - 1; + int mid; + if (A == null || A.size() == 0 || target <= A.get(0)) { + return 0; + } + //find the last number less than target + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A.get(mid) == target) {//Since no duplicates, return when found + return mid; + } else if (A.get(mid) < target) { + start = mid; + } else { + end = mid; + } + } + //Always 2 elements left to check, first:start, second: end + if (A.get(end) == target) { + return end; + } + if (A.get(end) < target) { + return end + 1; + } + if (A.get(start) == target) { + return start; + } + return start + 1; + + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search Range in Binary Search Tree .java b/Others/old records/LintCode-Backup/Search Range in Binary Search Tree .java new file mode 100644 index 0000000..b7a9423 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search Range in Binary Search Tree .java @@ -0,0 +1,60 @@ +/* +37% Accepted +Given two values k1 and k2 (where k1 < k2) and a root pointer to a Binary Search Tree. Find all the keys of tree in range k1 to k2. i.e. print all x such that k1<=x<=k2 and x is a key of given BST. Return all the keys in ascending order. + +Example +For example, if k1 = 10 and k2 = 22, then your function should print 12, 20 and 22. + + 20 + + / \ + + 8 22 + + / \ + +4 12 + +Tags Expand +Binary Tree Binary Search Tree +Recursive + +Thinking Process: +Find lowest and turn around. + If don’t hit the ground, keep digging: + if (root.val > k1) dig into root.left +Check current +Find maximum and turn around. + If don’t hit the ceiling, keep climbing: + if (root.val < k2) climb to root.right + +*/ + +public class Solution { + /** + * @param root: The root of the binary search tree. + * @param k1 and k2: range k1 to k2. + * @return: Return all keys that k1<=key<=k2 in ascending order. + */ + public ArrayList searchRange(TreeNode root, int k1, int k2) { + ArrayList result = new ArrayList(); + helper(result, root, k1, k2); + return result; + } + + public void helper(ArrayList result, TreeNode root, int k1, int k2) { + if (root == null) { + return; + } + if (root.val > k1) { + helper(result, root.left, k1, k2); + } + if (root.val >= k1 && root.val <= k2) { + result.add(root.val); + } + if (root.val < k2) { + helper(result, root.right, k1, k2); + } + } +} + diff --git a/Others/old records/LintCode-Backup/Search Rotated in Sorted Array II.java b/Others/old records/LintCode-Backup/Search Rotated in Sorted Array II.java new file mode 100644 index 0000000..f1f12b3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search Rotated in Sorted Array II.java @@ -0,0 +1,65 @@ +Allow duplicates之后: +因为最终binary search的结果也是O(n) +所以这道题要记得: 既然是O(n), 那来个简单的for loop 也就好了。 + +当然,要跟面试官提起来原因。别一上来就只有for。。。 +``` +/* +Follow up for "Search in Rotated Sorted Array": +What if duplicates are allowed? + +Would this affect the run-time complexity? How and why? + +Write a function to determine if a given target is in the array. + +Example +Tags Expand +Binary Search Sorted Array Array + +Thinking process: +This seems results in O(n) when allowing duplicates. Other than that, it's quite similar to Search In Rotated Sorted Array I. +*/ + +public class Solution { + /** + * param A : an integer ratated sorted array and duplicates are allowed + * param target : an integer to be search + * return : a boolean + */ + public boolean search(int[] A, int target) { + // write your code here + if (A.length == 0) { + return false; + } + + int start = 0; + int end = A.length - 1; + int mid; + + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A[mid] == target) {//Check central point + return true; + } + if (A[start] < A[mid]){//1st section is continous + if (A[start] <= target && target <= A[mid]) {//target in 1st section? + end = mid; + } else { + start = mid; + } + } else {//2nd section is continous + if (A[mid] <= target && target <= A[end]) {//target in 2nd section? + start = mid; + } else { + end = mid; + } + } + }//While + + return (A[start] == target) || (A[end] == target); + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search Rotated in Sorted Array.java b/Others/old records/LintCode-Backup/Search Rotated in Sorted Array.java new file mode 100644 index 0000000..7543d27 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search Rotated in Sorted Array.java @@ -0,0 +1,160 @@ +方法1: + 1. binay search break point + 2. binary search target + 注意等号,在判断target在前半段还是后半段:if (A[p1] <= target && target <= A[breakPoint]) + +方法2: + 还是把它先当做正常的sorted list开始搜。 + 但是在比较的时候,多比较一个A[start] < A[mid]? + 在1 和 2 里面分别讨论 target 的位置 + 1. A[start] < A[mid] ? + 说明在前半段 + - start mid + 2. A[start] > A[mid] + 说明 start 还在前半段,而mid在后半段 + - mid < target < end + - target < mid + + + +``` +/* +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +You are given a target value to search. If found in the array return its index, otherwise return -1. + +You may assume no duplicate exists in the array. + +Example +For [4, 5, 1, 2, 3] and target=1, return 2 + +For [4, 5, 1, 2, 3] and target=0, return -1 + +Tags Expand +Binary Search Array Sorted Array +*/ + +/* + Easy solution: + Find the break point, then decide which section to binary search +*/ +public class Solution { + + public int search(int[] A, int target) { + if (A == null || A.length == 0) { + return -1; + } + int p1 = 0; + int p2 = A.length - 1; + int start = p1; + int end = p2; + int mid = start + (end - start)/2; + //find break point + int breakPoint = 0; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + return mid; + } else if (A[mid] >= A[p1]) { + start = mid; + } else { + end = mid; + } + } + if (A[start] > A[end]) { + breakPoint = start; + } else { + breakPoint = end; + } + + if (A[p1] <= target && target <= A[breakPoint]) { + start = p1; + end = breakPoint; + } else { + start = breakPoint + 1; + end = p2; + } + + //search for target + while (start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + return mid; + } else if (A[mid] > target) { + end = mid; + } else { + start = mid; + } + } + + if (A[start] == target) { + return start; + } else if (A[end] == target) { + return end; + } + return -1; + } +} + + + +/* + Just 1 binary search: this is the better solution + //Observation: + //1. There is only one break point + //2. There has to be a side that's continous, either first section or second section. + //3. Need to locate that continous section, then check if target is part of the continous section + +*/ +public class Solution { + /** + *@param A : an integer rotated sorted array + *@param target : an integer to be searched + *return : an integer + */ + + public int search(int[] A, int target) { + // write your code here + if (A.length == 0) { + return -1; + } + + int start = 0; + int end = A.length - 1; + int mid; + + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A[mid] == target) {//Check central point + return mid; + } + if (A[start] < A[mid]){//1st section is continous + if (A[start] <= target && target <= A[mid]) {//target in 1st section? + end = mid; + } else { + start = mid; + } + } else {//2nd section is continous + if (A[mid] <= target && target <= A[end]) {//target in 2nd section? + start = mid; + } else { + end = mid; + } + } + }//While + + if (A[start] == target) { + return start; + } else if (A[end] == target) { + return end; + } else { + return -1; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search a 2D Matrix II.java b/Others/old records/LintCode-Backup/Search a 2D Matrix II.java new file mode 100644 index 0000000..c9c8710 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search a 2D Matrix II.java @@ -0,0 +1,80 @@ +根据给定的性质,找个点(left-bottom):每次有任何情况,只能往一个方向运行。 +每次删掉一行,或者一列 +``` +/* +Write an efficient algorithm that searches for a value in an m x n matrix, return the occurrence of it. + +This matrix has the following properties: + + * Integers in each row are sorted from left to right. + + * Integers in each column are sorted from up to bottom. + + * No duplicate integers in each row or column. + +Example +Consider the following matrix: + +[ + + [1, 3, 5, 7], + + [2, 4, 7, 8], + + [3, 5, 9, 10] + +] + +Given target = 3, return 2. + +Challenge +O(m+n) time and O(1) extra space + +*/ + +/* + Thoughts: 11.29.2015. LintCode updated. Practice again. + Understand that: + 1. Each row has exactly 1 instance of that integer, no duplicates. + 2. Each row begins with smallest number. So, if matrix[x][y] < target, first thing to do is x++. + 3. Each col ends with largest number. So if matrix[x][y] > target, + (no need to care x++ since it's alreay too large for this row), then simply just y--. + 4. If match, next step will be x--,y++. + x-- because it has to change a row; + y++ because [x-1, y] can't be the target since no duplicate in column + Beneftis of going from bottown-left: No matter which condition, always have 1 possible way to move. +*/ + +public class Solution { + /** + * @param matrix: A list of lists of integers + * @param: A number you want to search in the matrix + * @return: An integer indicate the occurrence of target in the given matrix + */ + public int searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return 0; + } + int row = matrix.length; + int col = matrix[0].length; + int x = row - 1; + int y = 0; + int count = 0; + while (x >= 0 && y < col) { + if (matrix[x][y] < target) { + y++; + } else if (matrix[x][y] > target) { + x--; + } else {//matrix[x][y] == target + count++; + x--; + y++; + } + } + return count; + } +} + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search a 2D Matrix.java b/Others/old records/LintCode-Backup/Search a 2D Matrix.java new file mode 100644 index 0000000..23759e1 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search a 2D Matrix.java @@ -0,0 +1,135 @@ +一行一行是从小到大,连续的: +2D转1D。 +Binary Search +``` +/* +Write an efficient algorithm that searches for a value in an m x n matrix. + +This matrix has the following properties: + + * Integers in each row are sorted from left to right. + + * The first integer of each row is greater than the last integer of the previous row. + +Example +Consider the following matrix: + +[ + + [1, 3, 5, 7], + + [10, 11, 16, 20], + + [23, 30, 34, 50] + +] + +Given target = 3, return true. + +Challenge +O(log(n) + log(m)) time + +Tags Expand +Binary Search Matrix + + +*/ + +/* + Thoughts: 11.29.2015 + The problem is updated on LintCode. Practice again. + Convert into 1D array. Binary Search +*/ +public class Solution { + /** + * @param matrix, a list of lists of integers + * @param target, an integer + * @return a boolean, indicate whether matrix contains target + */ + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } + int row = matrix.length; + int col = matrix[0].length; + int start = 0; + int end = row * col - 1; + int mid; + + while (start + 1 < end) { + mid = start + (end - start)/2; + int num = matrix[mid/col][mid%col]; + if (target == num) { + return true; + } else if (num < target) { + start = mid; + } else { + end = mid; + } + } + + return (matrix[start/col][start%col] == target || matrix[end/col][end%col] == target); + } +} + + + + + + + + +/* +Thinking process: +0. The elements are unique, no duplicates +Treat it as a 1-D array +Do binary search + 1. check head element + 2. find the element until only start & end element left + 3. Deal with start and end +*/ + +public class Solution { + /** + * @param matrix, a list of lists of integers + * @param target, an integer + * @return a boolean, indicate whether matrix contains target + */ + //Turn 2D array into 1D array and perform regular binary search + public boolean searchMatrix(ArrayList> matrix, int target) { + if(matrix.size() == 0) { + return false; + } + // write your code + int rows = matrix.size(); + int cols = matrix.get(0).size(); + int start = 0; + int end = rows * cols - 1; + int mid; + + while (start + 1 < end) {//This will leave exact 1 start and 1 end element for next code section + mid = start + (end - start) / 2; + int midVal = matrix.get(mid / cols).get(mid % cols); //trick to get element + + if (midVal == target) { + return true; + } else if (midVal < target) { + start = mid; + } else { + end = mid; + } + }//end while + + //Deal with the 1 start and 1 end element + int startVal = matrix.get(start / cols).get(start % cols); + int endVal = matrix.get(end / cols).get(end % cols); + if (startVal == target || endVal == target) { + return true; + } else { + return false; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Search for a Range.java b/Others/old records/LintCode-Backup/Search for a Range.java new file mode 100644 index 0000000..e498cb5 --- /dev/null +++ b/Others/old records/LintCode-Backup/Search for a Range.java @@ -0,0 +1,174 @@ +前后跑2个while loop。 找first/last occurance +``` +/* +Given a sorted array of integers, 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]. + +Example +Given [5, 7, 7, 8, 8, 10] and target value 8, +return [3, 4]. + +Tags Expand +Binary Search Array Sorted Array +*/ + +/* + Recap: 12.08.2015 + input sorted + 2 binary search while loop. + First one, keep looking for 1st occurnace. + Second one, keep looking for alst occurance. + + check border case: + A = [] + + +*/ +public class Solution { + public int[] searchRange(int[] A, int target) { + int[] rst = new int[]{-1, -1}; + if (A == null || A.length == 0) { + return rst; + } + int start = 0; + int end = A.length - 1; + int mid = start + (end - start)/2; + + //1st occurance. + int first = 0; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + if (mid - 1 >= 0 && A[mid - 1] == target) { + end = mid; + continue; + } + break; + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + if (A[start] == target) { + first = start; + } else if (A[mid] == target) { + first = mid; + } else if (A[end] == target) { + first = end; + } else { + return rst; + } + rst[0] = first; + + //check last occurance + int last = 0; + start = first; + end = A.length - 1; + while (start + 1 < end) { + mid = start + (end - start)/2; + if (A[mid] == target) { + if (mid + 1 < A.length && A[mid + 1] == target) { + start = mid; + continue; + } + break; + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + if (A[end] == target) { + last = end; + } else if (A[mid] == target) { + last = mid; + } else if (A[start] == target) { + last = start; + } else { + last = first; + } + rst[1] = last; + + return rst; + } +} + + + + + + + + + + +//Older solution: +public class Solution { + /** + *@param A : an integer sorted array + *@param target : an integer to be inserted + *return : a list of length 2, [index1, index2] + */ + public ArrayList searchRange(ArrayList A, int target) { + // write your code here + int start = 0; + int end = A.size() - 1; + int mid; + ArrayList bound = new ArrayList(); + bound.add(-1); + bound.add(-1); + + if ( A.size() == 0) { + return bound; + } + + //Left: + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A.get(mid) < target) { + start = mid; + } else if (A.get(mid) > target) { + end = mid; + } else { + end = mid;//Run to left + } + } + if (A.get(start) == target) {//Run to left + bound.set(0, start); + } else if (A.get(end) == target) { + bound.set(0, end); + } else { + return bound; + } + + //Right: + start = 0; + end = A.size() - 1; + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (A.get(mid) < target) { + start = mid; + } else if (A.get(mid) > target) { + end = mid; + } else { + start = mid;//Run to right + } + } + if (A.get(end) == target) {//Run to right + bound.set(1, end); + } else if (A.get(start) == target) { + bound.set(1, start); + } else { + return bound; + } + + return bound; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Segment Tree Build II.java b/Others/old records/LintCode-Backup/Segment Tree Build II.java new file mode 100644 index 0000000..4c8b25f --- /dev/null +++ b/Others/old records/LintCode-Backup/Segment Tree Build II.java @@ -0,0 +1,87 @@ +给的是Array。注意找区间内的max, assign给区间。 +想:区间break到底,像segment tree build I 里面一样最终也就是 start==end。也就是max=A[start] 或者A[end] +往上一层,其实max就是比较左右孩子。然后一次递推。每次找max其实都是在两个sub-tree里面比较sub-tree的max。 +这就好做了: +先分,找到left/right,比较max,在create current node,再append到当前node上面。 + +实际上是depth-first, 自底向上建立起的。 +``` +/* +The structure of Segment Tree is a binary tree which each node has two attributes start and end +denote an segment / interval. +start and end are both integers, they should be assigned in following rules: +The root's start and end is given by build method. +The left child of node A has start=A.left, end=(A.left + A.right) / 2. +The right child of node A has start=(A.left + A.right) / 2 + 1, end=A.right. +if start equals to end, there will be no children for this node. +Implement a build method with a given array, so that we can create a corresponding segment tree +with every node value represent the corresponding interval max value in the array, +return the root of this segment tree. + + +Example +Given [3,2,1,4]. The segment tree will be: + [0, 3] (max = 4) + / \ + [0, 1] (max = 3) [2, 3] (max = 4) + / \ / \ +[0, 0](max = 3) [1, 1](max = 2)[2, 2](max = 1) [3, 3] (max = 4) +Clarification +Segment Tree (a.k.a Interval Tree) is an advanced data structure which can support queries like: +which of these intervals contain a given point +which of these points are in a given interval +See wiki: Segment Tree Interval Tree +Tags Expand +Segment Tree +*/ + +/* +Thoughts: +Similar to Segment Tree, where the start and end are just : 0 and arrary.length -1. +For max value: How about a backgracking? SO: split and recursive build tree first; +each recursion, compare the returnning left/right child's max value, and then put into curr node's max. +Note: each leaf node will have start==end, so their max is really easy to figure out. +*/ + +/** + * Definition of SegmentTreeNode: + * public class SegmentTreeNode { + * public int start, end, max; + * public SegmentTreeNode left, right; + * public SegmentTreeNode(int start, int end, int max) { + * this.start = start; + * this.end = end; + * this.max = max + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + *@param A: a list of integer + *@return: The root of Segment Tree + */ + public SegmentTreeNode build(int[] A) { + if (A == null || A.length == 0) { + return null; + } + return buildHelper(0, A.length - 1, A); + } + + public SegmentTreeNode buildHelper(int start, int end, int[] A) { + if (start > end) { + return null; + } else if (start == end) { + return new SegmentTreeNode(start, end, A[end]); + } + + SegmentTreeNode leftChild = buildHelper(start, (start + end)/2, A); + SegmentTreeNode rightChild = buildHelper((start + end)/2 + 1, end, A); + + SegmentTreeNode node = new SegmentTreeNode(start, end, Math.max(leftChild.max, rightChild.max)); + node.left = leftChild; + node.right = rightChild; + return node; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Segment Tree Build.java b/Others/old records/LintCode-Backup/Segment Tree Build.java new file mode 100644 index 0000000..32660c8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Segment Tree Build.java @@ -0,0 +1,65 @@ +按定义: +左孩子:(A.left, (A.left+A.rigth)/2) +右孩子:((A.left+A.rigth)/2+1, A.right) +``` +/* +The structure of Segment Tree is a binary tree which each node has two attributes start and end denote an segment / interval. + +start and end are both integers, they should be assigned in following rules: + +The root's start and end is given by build method. +The left child of node A has start=A.left, end=(A.left + A.right) / 2. +The right child of node A has start=(A.left + A.right) / 2 + 1, end=A.right. +if start equals to end, there will be no children for this node. +Implement a build method with two parameters start and end, so that we can create a corresponding segment tree with every node has the correct start and end value, return the root of this segment tree. + +Example +Given start=0, end=3. The segment tree will be: + + [0, 3] + / \ + [0, 1] [2, 3] + / \ / \ + [0, 0] [1, 1] [2, 2] [3, 3] + +Given start=1, end=6. The segment tree will be: + + [1, 6] + / \ + [1, 3] [4, 6] + / \ / \ + [1, 2] [3,3] [4, 5] [6,6] + / \ / \ +[1,1] [2,2] [4,4] [5,5] + +Clarification +Segment Tree (a.k.a Interval Tree) is an advanced data structure which can support queries like: + +which of these intervals contain a given point +which of these points are in a given interval +See wiki: +Segment Tree +Interval Tree + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +public class Solution { + /** + *@param start, end: Denote an segment / interval + *@return: The root of Segment Tree + */ + public SegmentTreeNode build(int start, int end) { + if (start > end) { + return null; + } else if (start == end) { + return new SegmentTreeNode(start, end); + } + SegmentTreeNode node = new SegmentTreeNode(start, end); + node.left = build(start, (start + end)/2); + node.right = build((start + end)/2 + 1, end); + return node; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Segment Tree Modify.java b/Others/old records/LintCode-Backup/Segment Tree Modify.java new file mode 100644 index 0000000..f506afe --- /dev/null +++ b/Others/old records/LintCode-Backup/Segment Tree Modify.java @@ -0,0 +1,88 @@ +在segment tree里面找index. +找到就update it with value. +每次下一层以后,很可能(要么左手,要么右手)max就变了。所以每次都left.max and right.max compare一下。 +最后轮回到头顶,头顶一下包括头顶,就全部都是max了。 +``` +/* +For a Maximum Segment Tree, which each node has an extra value max to store the maximum value in this node's interval. + +Implement a modify function with three parameter root, index and value to change the node's value with [start, end] = [index, index] to the new given value. Make sure after this change, every node in segment tree still has the max attribute with the correct value. + +Example +For segment tree: + + [1, 4, max=3] + / \ + [1, 2, max=2] [3, 4, max=3] + / \ / \ +[1, 1, max=2], [2, 2, max=1], [3, 3, max=0], [4, 4, max=3] + +if call modify(root, 2, 4), we can get: + + [1, 4, max=4] + / \ + [1, 2, max=4] [3, 4, max=3] + / \ / \ +[1, 1, max=2], [2, 2, max=4], [3, 3, max=0], [4, 4, max=3] + +or call modify(root, 4, 0), we can get: + + [1, 4, max=2] + / \ + [1, 2, max=2] [3, 4, max=0] + / \ / \ +[1, 1, max=2], [2, 2, max=1], [3, 3, max=0], [4, 4, max=0] +Note +We suggest you finish problem Segment Tree Build and Segment Tree Query first. + +Challenge +Do it in O(h) time, h is the height of the segment tree. + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thought: + Renew index x with new value, and update the max value alone the way. + 1. Use segmenttree property to find that leaf, which is node.start == node.end == index. + 2. Along the way, whenever going to one segment/interval, compare left.max and right.max again, and update max. +*/ + +/** + * Definition of SegmentTreeNode: + * public class SegmentTreeNode { + * public int start, end, max; + * public SegmentTreeNode left, right; + * public SegmentTreeNode(int start, int end, int max) { + * this.start = start; + * this.end = end; + * this.max = max + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + *@param root, index, value: The root of segment tree and + *@ change the node's value with [index, index] to the new given value + *@return: void + */ + public void modify(SegmentTreeNode root, int index, int value) { + if (root.start == root.end && root.start == index) { + root.max = value; + return; + } + + //Divide and seawrch + int mid = (root.start + root.end)/2; + if (index <= mid) { + modify(root.left, index, value); + } else { + modify(root.right, index, value); + } + root.max = Math.max(root.left.max, root.right.max); + } +} + +``` diff --git a/Others/old records/LintCode-Backup/Segment Tree Query II.java b/Others/old records/LintCode-Backup/Segment Tree Query II.java new file mode 100644 index 0000000..30b6ea6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Segment Tree Query II.java @@ -0,0 +1,88 @@ +和 Segment Tree Query I 以及其他Segment Tree问题没啥区别。这个就是return个count。 +这个题目考的是:validate input source... +搞不清楚LintCode出这个题目干啥。 +``` +/* +For an array, we can build a SegmentTree for it, each node stores an extra attribute count to denote the number of elements in the the array which value is between interval start and end. (The array may not fully filled by elements) + +Design a query method with three parameters root, start and end, find the number of elements in the in array's interval [start, end] by the given root of value SegmentTree. + +Example +For array [0, 2, 3], the corresponding value Segment Tree is: + + [0, 3, count=3] + / \ + [0,1,count=1] [2,3,count=2] + / \ / \ + [0,0,count=1] [1,1,count=0] [2,2,count=1], [3,3,count=1] + +query(1, 1), return 0 + +query(1, 2), return 1 + +query(2, 3), return 2 + +query(0, 2), return 2 + +Note +It is much easier to understand this problem if you finished Segment Tree Buildand Segment Tree Query first. + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thoughts: + Since SegmentTree is already constructed, just use it to calculate count. + If all on left/right, easy, just return that portion. + If mid is between start,end, deal with it carefully. +*/ + +/** + * Definition of SegmentTreeNode: + * public class SegmentTreeNode { + * public int start, end, count; + * public SegmentTreeNode left, right; + * public SegmentTreeNode(int start, int end, int count) { + * this.start = start; + * this.end = end; + * this.count = count; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + *@param root, start, end: The root of segment tree and + * an segment / interval + *@return: The count number in the interval [start, end] + */ + public int query(SegmentTreeNode root, int start, int end) { + if (root == null || start > end) { + return 0; + } + if (root.start == start && root.end == end) { + return root.count; + } + //Check if over range + if ((start < root.start && end > root.end) || + (start < root.start && end < root.start) || + (start > root.end && end > root.end)) { + return 0; + } else if (start < root.start && end <= root.end) { + start = root.start; + } else if (start >= root.start && end > root.end) { + end = root.end; + } + int mid = (root.start + root.end)/2; + if (end <= mid) { + return query(root.left, start, end); + } + if (start > mid) { + return query(root.right, start, end); + } + return query(root.left, start, root.left.end) + query(root.right, root.right.start, end); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Segment Tree Query.java b/Others/old records/LintCode-Backup/Segment Tree Query.java new file mode 100644 index 0000000..05f9749 --- /dev/null +++ b/Others/old records/LintCode-Backup/Segment Tree Query.java @@ -0,0 +1,83 @@ +[start,end]跟mid相比,可能: +全在mid左 +全在mid右 +包含了mid: 这里要特别break into 2 query method + +按定义: +mid = (root.start + root.end)/2 +``` +/* +For an integer array (index from 0 to n-1, where n is the size of this array), in the corresponding SegmentTree, each node stores an extra attribute max to denote the maximum number in the interval of the array (index from start to end). + +Design a query method with three parameters root, start and end, find the maximum number in the interval [start, end] by the given root of segment tree. + +Example +For array [1, 4, 2, 3], the corresponding Segment Tree is: + + [0, 3, max=4] + / \ + [0,1,max=4] [2,3,max=3] + / \ / \ + [0,0,max=1] [1,1,max=4] [2,2,max=2], [3,3,max=3] +query(root, 1, 1), return 4 + +query(root, 1, 2), return 4 + +query(root, 2, 3), return 3 + +query(root, 0, 2), return 4 + +Note +It is much easier to understand this problem if you finished Segment Tree Build first. + +Tags Expand +LintCode Copyright Binary Tree Segment Tree +*/ + +/* + Thoughts: + Search the segment tree, and find the node that matches the interval (start, end) + if (start == root.start && right == root.end) return max; + if end <= (root.left + root.right) / 2 : go left; + if start> (root.left + root.right): go right + However if start <= mid < end, break it into 2 segments and meger afterwards. +*/ +/** + * Definition of SegmentTreeNode: + * public class SegmentTreeNode { + * public int start, end, max; + * public SegmentTreeNode left, right; + * public SegmentTreeNode(int start, int end, int max) { + * this.start = start; + * this.end = end; + * this.max = max + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + *@param root, start, end: The root of segment tree and + * an segment / interval + *@return: The maximum number in the interval [start, end] + */ + public int query(SegmentTreeNode root, int start, int end) { + if (start == root.start && end == root.end) { + return root.max; + } + int mid = (root.start + root.end)/2; + if (end <= mid) { + return query(root.left, start, end); + } + if (start > mid) { + return query(root.right, start, end); + } + //start <= mid && end > mid + int maxLeft = query(root.left, start, root.left.end); + int maxRight = query(root.right, root.right.start, end); + + return Math.max(maxLeft, maxRight); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Serilization and Deserialization Of Binary Tree.java b/Others/old records/LintCode-Backup/Serilization and Deserialization Of Binary Tree.java new file mode 100644 index 0000000..671614e --- /dev/null +++ b/Others/old records/LintCode-Backup/Serilization and Deserialization Of Binary Tree.java @@ -0,0 +1,86 @@ +/* +Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'. + +There is no limit of how you deserialize or serialize a binary tree, you only need to make sure you can serialize a binary tree to a string and deserialize this string to the original structure. + +Example +An example of testdata: Binary tree {3,9,20,#,#,15,7}, denote the following structure: + + 3 + / \ + 9 20 + / \ + 15 7 +Our data serialization use bfs traversal. This is just for when you got wrong answer and want to debug the input. + +You can use other method to do serializaiton and deserialization. + +Tags Expand +Binary Tree + +Thinking process: +1. Carefully turn the binary tree into a string: use pre-order in this example. +2. Use a global variable to track the data(data string will be cut in different levels of recursion). +The concept is very easy tho, just need to carefully code it up. + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +class Solution { + /** + * This method will be invoked first, you should design your own algorithm + * to serialize a binary tree which denote by a root node to a string which + * can be easily deserialized by your own "deserialize" method later. + */ + public String serialize(TreeNode root) { + if (root == null) { + return "#,"; + } + String mid = root.val + ","; + String left = serialize(root.left); + String right = serialize(root.right); + mid += left + right; + return mid; + } + + private String data = ""; + /** + * This method will be invoked second, the argument data is what exactly + * you serialized at method "serialize", that means the data is not given by + * system, it's given by your own serialize method. So the format of data is + * designed by yourself, and deserialize it here as you serialize it in + * "serialize" method. + */ + public TreeNode deserialize(String data) { + this.data = data; + return desHelper(); + } + + public TreeNode desHelper() { + if (this.data.indexOf("#,") == 0) { + this.data = this.data.substring(this.data.indexOf(",") + 1); + return null; + } + String midVal = this.data.substring(0, this.data.indexOf(",")); + TreeNode mid = new TreeNode(Integer.parseInt(midVal)); + this.data = this.data.substring(this.data.indexOf(",") + 1); + TreeNode left = desHelper(); + TreeNode right = desHelper(); + mid.left = left; + mid.right = right; + return mid; + } +} + + + diff --git a/Others/old records/LintCode-Backup/Single Number II.java b/Others/old records/LintCode-Backup/Single Number II.java new file mode 100644 index 0000000..695efc8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Single Number II.java @@ -0,0 +1,37 @@ +/* +Given 3*n + 1 numbers, every numbers occurs triple times except one, find it. +Example +Given [1,1,2,3,3,3,2,2,4,1] return 4 + +Challenge +One-pass, constant extra space +Thinking process: +Still using bit manipulation. We need to erase all of the 3-appearance number and leave the single number out. A few steps: +Store the final result by continuously bit OR with the result variable. +Want to XOR the 3 numbers, but can’t erase them as if only 2 duplicate numbers:Consider the number as 3-based number, so XOR can be understand this way + when add 3 numbers together, add each individual bit. If the sum is 3, then set it as 0. If not 3, leave as is. +3. Store the bits in a integer array, which simulates a binary version of the integer +4. When each bit’s XOR process finishes, bit OR it with result +*/ + +public class Solution { + public int singleNumberII(int[] A) { + if (A == null || A.length == 0) { + return -1; + } + //present the XOR results in binary format + int[] bits = new int[32]; + int rst = 0; + for (int i = 0; i < 32; i++) { + for (int j = 0; j < A.length; j++){ + //XOR the numbers in a 3-base fashion. Whenever bit[i] has a number 3, set it back to 0. + bits[i] += A[j] >> i & 1; + bits[i] %= 3; + } + //OR it to the result. However, each time only the i - spot is updated with the bits[i]. + rst |= bits[i] << i; + } + return rst; + } +} + diff --git a/Others/old records/LintCode-Backup/Single Number III.java b/Others/old records/LintCode-Backup/Single Number III.java new file mode 100644 index 0000000..556f15b --- /dev/null +++ b/Others/old records/LintCode-Backup/Single Number III.java @@ -0,0 +1,51 @@ +/* +Given 2*n + 2 numbers, every numbers occurs twice except two, find them. + +Example +Given [1,2,2,3,4,4,5,3] return 1 and 5 + +Challenge +O(n) time, O(1) extra space. + +Thinking Process: +The 2 exception must have this feature: a ^ b != 0, since they are different +Still want to do 2n + 1 problem as in Single Number I, then we need to split a and b into 2 groups and deal with two 2n+1 problems +Assume c = a^b, there mush be a bit where a and b has the difference, so that bit in c is 1. +Find this bit position and use it to split the group: shift number in the array by ‘bit-position’ indexes. If the shifted number has 1 at the ‘bit-position’, set it to one group; otherwise to another group. +*/ + +public class Solution { + /** + * @param A : An integer array + * @return : Two integers + */ + public List singleNumberIII(int[] A) { + if (A == null || A.length == 0) { + return null; + } + List rst = new ArrayList(); + int xor = 0; + for (int i = 0; i < A.length; i++) { + xor ^= A[i]; + } + int bitOnePos = 0; + for (int i = 0; i < 32; i++) { + if ((xor >> i & 1) == 1) { + bitOnePos = i; + } + } + int rstA = 0; + int rstB = 0; + for (int i = 0; i < A.length; i++) { + if ((A[i] >> bitOnePos & 1) == 1) { + rstA ^= A[i]; + } else { + rstB ^= A[i]; + } + } + rst.add(rstA); + rst.add(rstB); + return rst; + } +} + diff --git a/Others/old records/LintCode-Backup/Single Number.java b/Others/old records/LintCode-Backup/Single Number.java new file mode 100644 index 0000000..f67f2e2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Single Number.java @@ -0,0 +1,40 @@ +/* +62% Accepted +Given 2*n + 1 numbers, every numbers occurs twice except one, find it. + +Example +Given [1,2,2,1,3,4,3], return 4 + +Challenge +One-pass, constant extra space + +Tags Expand +Greedy + +Manipulate bits: +Thinking process: +One-pass and constant extra space. +since all numbers appears twice, consider them as in bits format. Two identical number XOR will be zero. If we XOR everything double-numbers together, it will be zero. At the end, we use o XOR our target number, the result is actually the target number. +Very smart trick to use bits. +In order to compare from index 0 to the end, we need to extract index 0 first as result before for loop. And start for loop at i = 1. +*/ + +public class Solution { + /** + *@param A : an integer array + *return : a integer + */ + public int singleNumber(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int rst = A[0]; + for (int i = 1; i < A.length; i++) { + rst = rst ^ A[i]; + } + return rst; + } +} + + + diff --git a/Others/old records/LintCode-Backup/Singleton.java b/Others/old records/LintCode-Backup/Singleton.java new file mode 100644 index 0000000..7a5b4d2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Singleton.java @@ -0,0 +1,45 @@ +/* +Singleton is a most widely used design pattern. If a class has and only has one instance at every moment, we call this design as singleton. For example, for class Mouse (not a animal mouse), we should design it in singleton. + +You job is to implement a getInstance method for given class, return the same instance of this class every time you call this method. + + +Example +In Java: + +A a = A.getInstance(); +A b = A.getInstance(); +a should equal to b. + +Challenge +If we call getInstance concurrently, can you make sure your code could run correctly? + +Tags Expand +LintCode Copyright OO Design + +Thoughts: +... +Was not clear to me. Need to loop up more on synchronized/volatile +Good reference: +http://www.cnblogs.com/EdwardLiu/p/4443230.html + +*/ + + +class Solution { + public static volatile Solution solution = null; + /** + * @return: The same instance of this class every time + */ + public static Solution getInstance() { + if (solution == null) { + synchronized (Solution.class) { + // Double check + if (solution == null) { + solution = new Solution(); + } + } + } + return solution; + } +}; diff --git a/Others/old records/LintCode-Backup/Sliding Window Maximum.java b/Others/old records/LintCode-Backup/Sliding Window Maximum.java new file mode 100644 index 0000000..bb9bde0 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sliding Window Maximum.java @@ -0,0 +1,75 @@ +妙:用deque数据结构(实际上采用LinkedList的形式)来做一个递减的queue. +每次把小于当前node的,全部剔除,剩下的,自然就是:最大的>第二大的>第三大的...ETC. +为啥可以不管不无地剔除? +因为我们只在乎最大值的存在;而任何小于当前(正要新就加进去的)值的,反正以后也成不了最大值,于是扔掉! +``` +/* +Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving. + +Example +For array [1, 2, 7, 7, 8], moving window size k = 3. return [7, 7, 8] + +At first the window is at the start of the array like this + +[|1, 2, 7| ,7, 8] , return the maximum 7; + +then the window move one step forward. + +[1, |2, 7 ,7|, 8], return the maximum 7; + +then the window move one step forward again. + +[1, 2, |7, 7, 8|], return the maximum 8; + +Challenge +o(n) time and O(k) memory + +Tags Expand +LintCode Copyright Deque +*/ + +/* + Thoughts: + Create deque: ArrayDeque, or LinkedList + Maintain a decreasing deque that stores indexes: so peekFirst() is always the maxium value's index + To do that, we need: whenever adding a new value, remove all values in the deque that are smaller than current node. + Loop k elements first, then process the rest + O(n) time, O(k) space +*/ +public class Solution { + /** + * @param nums: A list of integers. + * @return: The maximum number inside the window at each moving. + */ + public ArrayList maxSlidingWindow(int[] nums, int k) { + ArrayList rst = new ArrayList(); + if (nums == null || nums.length == 0 || k < 0) { + return rst; + } + Deque deque = new LinkedList(); + for (int i = 0; i < k; i++) { + while (!deque.isEmpty() && nums[deque.peekLast()] <= nums[i]) { + deque.pollLast(); + } + deque.offerLast(i); + } + + for (int i = k; i < nums.length; i++) { + rst.add(nums[deque.peekFirst()]); + if (!deque.isEmpty() && deque.peekFirst() <= i - k) { + deque.pollFirst(); + } + while (!deque.isEmpty() && nums[deque.peekLast()] <= nums[i]) { + deque.pollLast(); + } + deque.offerLast(i); + } + + //Last move's result needs to be recorded: + rst.add(nums[deque.peekFirst()]); + return rst; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Sliding Window Median.java b/Others/old records/LintCode-Backup/Sliding Window Median.java new file mode 100644 index 0000000..dd954a3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sliding Window Median.java @@ -0,0 +1,110 @@ +Median还是用min-heap 和 max-heap。 +移动窗口2step: +1. 加一个数。 +2. 减一个数。 +加减时看好,是从前面的maxheap里面抽,还是从后面的minHeap里面抽。 +抽完balance一下。 + +记得: +左边的maxHeap总有 x+1或者x个数字。 +后边minHeap应该一直有x个数字。 + +``` +/* +Given an array of n integer, and a moving window(size k), move the window at each iteration from the start of the array, find the median of the element inside the window at each moving. (If there are even numbers in the array, return the N/2-th number after sorting the element in the window. ) + +Example +For array [1,2,7,8,5], moving window size k = 3. return [2,7,7] + +At first the window is at the start of the array like this + +[ | 1,2,7 | ,8,5] , return the median 2; + +then the window move one step forward. + +[1, | 2,7,8 | ,5], return the median 7; + +then the window move one step forward again. + +[1,2, | 7,8,5 | ], return the median 7; + +Challenge +O(nlog(n)) time + +Tags Expand +LintCode Copyright Heap +*/ + +//NOT DONE +/* +Thoughts: +1. from 0 ~k, populate the maxHeap and minHeap +2. i = k ~ nums.length, add one value and minus one value, calculate median +*/ + +public class Solution { + PriorityQueue minHeap; + PriorityQueue maxHeap; + + /** + * @param nums: A list of integers. + * @return: The median of the element inside the window at each moving. + */ + public ArrayList medianSlidingWindow(int[] nums, int k) { + ArrayList rst = new ArrayList(); + if (nums == null || nums.length == 0 || k <= 0) { + return rst; + } + minHeap = new PriorityQueue(); + maxHeap = new PriorityQueue(10, new Comparator(){ + public int compare(Integer x, Integer y){ + return y - x; + } + }); + maxHeap.offer(nums[0]); + + for (int i = 1; i < k; i++) { + add(nums[i]); + } + + rst.add(maxHeap.peek()); + for (int i = k; i < nums.length; i++) { + add(nums[i]); + remove(nums[i - k]); + rst.add(maxHeap.peek()); + } + return rst; + } + + public void add(int val) { + int preMedian = maxHeap.peek(); + if (val > preMedian) { + minHeap.offer(val); + } else { + maxHeap.offer(val); + } + balance(); + } + + public void remove(int val) { + int preMedian = maxHeap.peek(); + if (val > preMedian) { + minHeap.remove(val); + } else { + maxHeap.remove(val); + } + balance(); + } + + public void balance() { + if (maxHeap.size() > minHeap.size() + 1) { + minHeap.offer(maxHeap.poll()); + } else if (maxHeap.size() < minHeap.size()) { + maxHeap.offer(minHeap.poll()); + } + } + +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Sort Color.java b/Others/old records/LintCode-Backup/Sort Color.java new file mode 100644 index 0000000..6128e27 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sort Color.java @@ -0,0 +1,82 @@ +/* +Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. + +Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. + +Example +Note +You are not suppose to use the library's sort function for this problem. + +Clarification +Follow up: +A rather straight forward solution is a two-pass algorithm using counting sort. +First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. + +Could you come up with an one-pass algorithm using only constant space? + +Tags Expand +Two Pointers Sort Array + +Thoughts; +A easier version of Sort ColorII. Using the exact same code with different k number. Note, now k is start from 0. + +*/ + +class Solution { + /** + * @param nums: A list of integer which is 0, 1 or 2 + * @return: nothing + */ + public void sortColors(int[] colors) { + if (colors == null || colors.length == 0) { + return; + } + int end = colors.length - 1; + int k = 2; // 3 different colors + for (int i = 0; i < k; i++) { + end = helper(colors, 0, end, k - i - 1); + } + } + + public void swap(int[] colors, int x, int y){ + int temp = colors[x]; + colors[x] = colors[y]; + colors[y] = temp; + } + + public int helper(int[] colors, int start, int end, int pivot) { + int low = start; + int high = end; + while (low <= high) { + while(low < high && colors[low] <= pivot) { + low++; + } + while(high > 0 && colors[high] > pivot) { + high--; + } + if (low <= high) { + swap(colors, low, high); + low++; + high--; + } + } + return low - 1; + } +} + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Sort Colors II.java b/Others/old records/LintCode-Backup/Sort Colors II.java new file mode 100644 index 0000000..a272ffe --- /dev/null +++ b/Others/old records/LintCode-Backup/Sort Colors II.java @@ -0,0 +1,84 @@ +/* +Given an array of n objects with k different colors (numbered from 1 to k), sort them so that objects of the same color are adjacent, with the colors in the order 1, 2, ... k. + +Example +GIven colors=[3, 2, 2, 1, 4], k=4, your code should sort colors in-place to [1, 2, 2, 3, 4]. + +Note +You are not suppose to use the library's sort function for this problem. + +Challenge +A rather straight forward solution is a two-pass algorithm using counting sort. That will cost O(k) extra memory. + +Can you do it without using extra memory? + +Tags Expand +Two Pointers Sort + +Thoughts (Need to revist and think about this, very interesting) +Doing quick sort partition for K -1 times. +1. Use K - 1 value as pivot +2. Starting from 0, whenever low0, and greater than pivot, high-- +4. Result: only swap when low and high have disagreement on the pivot value. + +*/ + +class Solution { + /** + * @param colors: A list of integer + * @param k: An integer + * @return: nothing + */ + public void sortColors2(int[] colors, int k) { + if (colors == null || colors.length == 0 || k <= 0) { + return; + } + int end = colors.length - 1; + for (int i = 0; i < k - 1; i++) { + end = helper(colors, 0, end, k - i - 1); + } + } + + public void swap(int[] colors, int x, int y){ + int temp = colors[x]; + colors[x] = colors[y]; + colors[y] = temp; + } + + public int helper(int[] colors, int start, int end, int pivot) { + int low = start; + int high = end; + while (low <= high) { + while(low < high && colors[low] <= pivot) { + low++; + } + while(high > 0 && colors[high] > pivot) { + high--; + } + if (low <= high) { + swap(colors, low, high); + low++; + high--; + } + } + return low - 1; + } +} + + + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Sort Letters by Case.java b/Others/old records/LintCode-Backup/Sort Letters by Case.java new file mode 100644 index 0000000..c136c97 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sort Letters by Case.java @@ -0,0 +1,64 @@ +/* +Given a string which contains only letters. Sort it by lower case first and upper case second. + +Example +For "abAcD", a reasonable answer is "acbAD" + +Note +It's not necessary to keep the original order of lower-case letters and upper case letters. + +Challenge +Do it in one-pass and in-place. + +Tags Expand +String Two Pointers LintCode Copyright Sort + +Thoughts: +Another two pointer sorting. +Difference: use a ASCII code 'a' as the pivot. all the letters that from a ~ z +have bigger integer values, and A~Z have small integer values. +This problem requires lowcase+upperCase, so we'd sort the list from high to low. +NOTE: in the 2 while loop, the it's always having ">=' + +*/ + + +public class Solution { + /** + *@param chars: The letter array you should sort by Case + *@return: void + */ + public void sortLetters(char[] chars) { + if (chars == null || chars.length == 0) { + return; + } + char pivot = 'a'; + int start = 0; int end = chars.length - 1; + while (start <= end) { + while (start <= end && chars[start] >= pivot) { + start++; + } + while (start <= end && chars[end] < pivot) { + end--; + } + if (start <= end) { + char temp = chars[end]; + chars[end] = chars[start]; + chars[start] = temp; + start++; + end--; + } + } + } +} + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Sort List.java b/Others/old records/LintCode-Backup/Sort List.java new file mode 100644 index 0000000..78c4b97 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sort List.java @@ -0,0 +1,135 @@ +Merge sort: + 1. find middle. 快慢指针 + 2. Merge: 假设given list A, B 已经是sorted, 然后按照大小,混合。 + 3. Sort: 切开两半,先sort前半, 如果先sort了mid.next~end, sort后,中间点mid.next == null,再sort前半段。 + 然后mege. + 要recursively call itself. + +Quick sort: +想做可以看讲义:http://www.jiuzhang.com/solutions/sort-list/ + +但是quick sort不建议用在list上面。 + +排列list, merge sort可能更可行和合理。原因分析在下面, 以及: http://www.geeksforgeeks.org/why-quick-sort-preferred-for-arrays-and-merge-sort-for-linked-lists/ + +``` +/* +28% Accepted +Sort a linked list in O(n log n) time using constant space complexity. + +Example +Given 1-3->2->null, sort it to 1->2->3->null. + +Tags Expand +Linked List + + +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ + + + + +/* + Recap:12.09.2015. practice merge sort +Thinking process: +1.Divide and conquer +2. can use merge sort or quick sort. Used merge sort here. +3. Find middle +4. Sort each side recursively. +5. merge function. +Note: when checking null, node != null should be in front of node.next != null. Because if node is alreay null, node.next gives exception. + +*/ + + + +public class Solution { + public ListNode findMiddle(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + public ListNode merge(ListNode left, ListNode right) { + ListNode dummy = new ListNode(0); + ListNode head = dummy; + while (left != null && right != null) { + if (left.val < right.val) { + head.next = left; + left = left.next; + } else { + head.next = right; + right = right.next; + } + head = head.next; + } + if (left != null) { + head.next = left; + } else if (right != null){ + head.next = right; + } + return dummy.next; + } + + /* + * @param head: The head of linked list. + * @return: You should return the head of the sorted linked list, + using constant space complexity. + */ + public ListNode sortList(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode mid = findMiddle(head); + ListNode left = sortList(mid.next); + mid.next = null; + ListNode right = sortList(head); + return merge(left, right); + } + + +} + + +/* + 12.09.2015: http://www.jiuzhang.com/solutions/sort-list/ + Quick sort. + + Didn't do this myself yet. This is because Quick sort in general is not so good for list. + Quick sort requires a lot random access to elements, which turns into worst case O(n) time to access a element + in list. So it can be worse to o(n^2). + So here Merge sort is prefered. + + Quick sort is prefered for array sort, partition. + + Merge sort is prefered for list sort +*/ + +public class Solution { + /* + * @param head: The head of linked list. + * @return: You should return the head of the sorted linked list, + using constant space complexity. + */ + public ListNode sortList(ListNode head) { + // write your code here + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Space Replacement.java b/Others/old records/LintCode-Backup/Space Replacement.java new file mode 100644 index 0000000..cd8ca45 --- /dev/null +++ b/Others/old records/LintCode-Backup/Space Replacement.java @@ -0,0 +1,55 @@ +/* +Write a method to replace all spaces in a string with %20. The string is given in a characters array, you can assume it has enough space for replacement and you are given the true length of the string. + +Example +Given "Mr John Smith", length = 13. + +The string after replacement should be "Mr%20John%20Smith". + +Note +If you are using Java or Python,please use characters array instead of string. + +Challenge +Do it in-place. + +Tags Expand +String Cracking The Coding Interview + +Thoughts: +Overriding the array from the back to front. +This is because as we re-writing the string from the back, stuff at head of the string does not change yet. +This is wonderful:) + +*/ + + +public class Solution { + /** + * @param string: An array of Char + * @param length: The true length of the string + * @return: The true length of new string + */ + public int replaceBlank(char[] string, int length) { + if (string == null || string.length == 0) { + return 0; + } + int count = 0; + for (char c : string) { + if (c == ' ') { + count += 2; + } + } + int lastIndex = length + count - 1; + //from back to front: + for (int i = length - 1; i >= 0; i--) { + if (string[i] == ' ') { + string[lastIndex--] = '0'; + string[lastIndex--] = '2'; + string[lastIndex--] = '%'; + } else { + string[lastIndex--] = string[i]; + } + } + return length + count; + } +} diff --git a/Others/old records/LintCode-Backup/Sqrt(x).java b/Others/old records/LintCode-Backup/Sqrt(x).java new file mode 100644 index 0000000..7a50108 --- /dev/null +++ b/Others/old records/LintCode-Backup/Sqrt(x).java @@ -0,0 +1,45 @@ +/* +Implement int sqrt(int x). + +Compute and return the square root of x. + +Example +sqrt(3) = 1 + +sqrt(4) = 2 + +sqrt(5) = 2 + +sqrt(10) = 3 +Challenge +O(log(x)) + +Tags Expand +Binary Search + +Thinking process: +Binary search. While loop until the head and tail meets. +*/ + +class Solution { + /** + * @param x: An integer + * @return: The sqrt of x + */ + public int sqrt(int x) { + long start = 0; + long end = x; + while (end >= start) { + long mid = start + (end - start) / 2; + if (mid * mid > x) { + end = mid - 1; + } else if (mid * mid < x) { + start = mid + 1; + } else { + return (int)mid; + } + } + //When start > end, while loop ends. That means, end must be the largest possible integer that end^2 is closest to x. + return (int)end; + } +} diff --git a/Others/old records/LintCode-Backup/Stone Game.java b/Others/old records/LintCode-Backup/Stone Game.java new file mode 100644 index 0000000..7ebbf4d --- /dev/null +++ b/Others/old records/LintCode-Backup/Stone Game.java @@ -0,0 +1,83 @@ +这个DP有点诡异. 需要斟酌。 +NOT DONE YET +``` +/* +There is a stone game.At the beginning of the game the player picks n piles of stones in a line. + +The goal is to merge the stones in one pile observing the following rules: + +At each step of the game,the player can merge two adjacent piles to a new pile. + +The score is the number of stones in the new pile. + +You are to determine the minimum of the total score. + +Example +[3, 4, 3] return 17 + +[1, 1, 1, 1] return 8 + +[4, 4, 5, 9] return 43 + +Tags Expand +Dynamic Programming +*/ + +/* +Thoughts: +Based on given outline. +sum[i][j] = stone sum between i and j +f[i][j]: min cost/score if we merge ith pile into jth pile. It can be f[0][1], f[0][2].. or our final result f[0][n-1] +break it by k and check both side f[start][k] and f[start][k+1]; +Tricky: add sum[start][end] at the end. +*/ + +public class Solution { + /** + * @param A an integer array + * @return an integer + */ + public int stoneGame(int[] A) { + // Algorithm: Dynamic Programming + // state: f[start][end] denote the minimum score that we can get if we merge stones from start-th pile to end-th pile into one pile. + // function: f[start][end] = min{f[start][k] + f[k + 1][end] + sum[start][end]} + + if (A == null || A.length == 0) { + return 0; + } + + int n = A.length; + + // initialize f[i][i] + int[][] f = new int[n][n]; + for (int i = 0; i < n; i++) { + f[i][i] = 0; + } + + // preparation for sum[i][j] + int[][] sum = new int[n][n]; + sum[0][0] = A[0]; + for (int i = 0; i < n; i++) { + sum[i][i] = A[i]; + for (int j = i + 1; j < n; j++) { + sum[i][j] = sum[i][j - 1] + A[j]; + } + } + + // dp + // delta is the distance between the start and end + for (int delta = 1; delta < n; delta++) { + for (int start = 0; start < n - delta; start++) { + int end = start + delta; + //initialize f[start][end] + f[start][end] = Integer.MAX_VALUE; + for (int k = start; k < end; k++) { + f[start][end] = Math.min(f[start][end], f[start][k] + f[k + 1][end] + sum[start][end]); + } + } + } + + return f[0][n - 1]; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/StrStr.java b/Others/old records/LintCode-Backup/StrStr.java new file mode 100644 index 0000000..249ac56 --- /dev/null +++ b/Others/old records/LintCode-Backup/StrStr.java @@ -0,0 +1,57 @@ +/* +StrStr: +strStr My Submissions + +19% Accepted +strstr (a.k.a find sub string), is a useful function in string operation. You task is to implement this function. + +For a given source string and a target string, you should output the "first" index(from 0) of target string in source string. + +If target is not exist in source, just return -1. + +Example +If source="source" and target="target", return -1. + +If source="abcdabcdefg" and target="bcd", return 1. + +Challenge +O(n) time. + +Clarification +Do I need to implement KMP Algorithm in an interview? + + - Not necessary. When this problem occurs in an interview, the interviewer just want to test your basic implementation ability. + +Tags Expand +Basic Implementation String + +Thinking process: +Two Pointer. +String Null case. +Break Statement. + + +Check position i+j of source and position j of target. If not match, break out. +If j matches target.length(), means target is fully embedded in source. +return start point of target in source: i +*/ +public int strStr(String source, String target) { + //Check Null + if(source == null || target == null){ + return -1; + } + //Two Pointer check for target + int i,j; + for (i = 0; i < source.length() - target.length() + 1; i++){ + for (j = 0; j < target.length(); j++){ + if (source.charAt(i+j) != target.charAt(j)){ + break; + } + } + if( j == target.length()){ + return i; + } + } + //'target' not found: + return -1; +} diff --git a/Others/old records/LintCode-Backup/String to Integer(atoi).java b/Others/old records/LintCode-Backup/String to Integer(atoi).java new file mode 100644 index 0000000..9c7f895 --- /dev/null +++ b/Others/old records/LintCode-Backup/String to Integer(atoi).java @@ -0,0 +1,122 @@ +E + +方法1: 问清情况,一点一点把case都涉及到。 + +方法2: 用regular expression。if (!str.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)")). 猛了一点 + +``` +/* +Implement function atoi to convert a string to an integer. + +If no valid conversion could be performed, a zero value is returned. + +If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. + +Example +"10" => 10 + +"-1" => -1 + +"123123123123123" => 2147483647 + +"1.0" => 1 + +Tags Expand +Basic Implementation String + +*/ + + +/* +02.02.2016 from leetcode +Requirements for atoi: +The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. + +The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function. + +If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed. + +If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned. +*/ +public class Solution { + public int myAtoi(String str) { + + if (str == null) { + return 0; + } + str = str.trim(); + if (str.length() == 0) { + return 0; + } + + char[] arr = str.toCharArray(); + String rst = ""; + for (int i = 0; i < arr.length; i++) { + char c = arr[i]; + if (i == 0 && (c == '+' || c == '-')) { + rst += c; + } else if (c < '0' || c > '9') { + break; + } else { + rst += c; + } + } + if (rst.length() == 0 || rst.equals("+") || rst.equals("-")) { + return 0; + } + if (rst.length() > 11) { + return rst.charAt(0) == '-' ? Integer.MIN_VALUE : Integer.MAX_VALUE; + } + long largeNum = Long.parseLong(rst); + if (largeNum > Integer.MAX_VALUE || largeNum < Integer.MIN_VALUE) { + return largeNum > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + return Integer.parseInt(rst); + } +} + + + +/* + +Thoughts: +First idea: why not using Integer.parseInt(str)? Maybe that's too costly, and maybe it does not over all possible integers? +Can we just use a Long.parseLong(str) ? + +Issues to check: +Long is not enough, because we might be getting decimal point. So we can use Double here. +String might have space: remove all " " +String might have char of other kind: check each individual char if isNaN() + +It looks like somewhere we'd need to use regular exp to search for pattern, and remove space. + +Note: need to ask if things like '21lintcode' can be considered as partial-integer and return 21. This is a more complex case, even after reg exp. + +*/ + +public class Solution { + /** + * @param str: A string + * @return An integer + */ + public int atoi(String str) { + if (str == null || str.length() == 0) { + return 0; + } + str = str.replaceAll("\\s",""); + if (!str.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)")) { + return 0; + } + double rst = Double.parseDouble(str); + if (rst > Integer.MAX_VALUE) { + return Integer.MAX_VALUE; + } else if (rst < Integer.MIN_VALUE) { + return Integer.MIN_VALUE; + } else { + return (int)rst; + } + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Subarray Sum Closest.java b/Others/old records/LintCode-Backup/Subarray Sum Closest.java new file mode 100644 index 0000000..8422953 --- /dev/null +++ b/Others/old records/LintCode-Backup/Subarray Sum Closest.java @@ -0,0 +1,147 @@ +/* +Given an integer array, find a subarray with sum closest to zero. Return the indexes of the first number and last number. + +Example +Given [-3, 1, 1, -3, 5], return [0, 2], [1, 3], [1, 1], [2, 2] or [0, 4] + +Challenge +O(nlogn) time + +Tags Expand +Subarray Sort + +Thoughts: +Took a me a while to think through how to find the closest sum to 0. +Credits should be given to: http://rafal.io/posts/subsequence-closest-to-t.html +*/ + + +class CustomComparator implements Comparator { + public int compare(int[] a, int[] b) { + return Integer.compare(a[0], b[0]); + } +} + +public class Solution { + + /** + * @param nums: A list of integers + * @return: A list of integers includes the index of the first number + * and the index of the last number + */ + public ArrayList subarraySumClosest(int[] nums) { + ArrayList rst = new ArrayList(); + if(nums == null || nums.length == 0) { + return rst; + } + if (nums.length == 1) { + rst.add(0); rst.add(0); + return rst; + } + int[][] culmulate = new int[nums.length][2]; + culmulate[0][0] = nums[0]; + culmulate[0][1] = 0; + for (int i = 1; i < nums.length; i++) { + culmulate[i][0] = culmulate[i - 1][0] + nums[i]; + culmulate[i][1] = i; + } + + Arrays.sort(culmulate, new CustomComparator()); + int min = Integer.MAX_VALUE; + int start = 0; + int end = 0; + for (int i = 0; i < nums.length - 1; i++) { + int temp = culmulate[i + 1][0] - culmulate[i][0]; + if (temp <= min) { + min = temp; + start = culmulate[i][1]; + end = culmulate[i + 1][1]; + } + } + if (start < end) { + rst.add(start + 1); + rst.add(end); + } else { + rst.add(end + 1); + rst.add(start); + } + return rst; + } +} + + + + + +//I also had to run a little java program locally to test/debug: +/* + +import java.lang.*; +import java.util.*; + +class CustomComparator implements Comparator { + public int compare(int[] a, int[] b) { + return Integer.compare(a[0], b[0]); + } +} + +public class test { + public ArrayList subarraySumClosest(int[] nums) { + ArrayList rst = new ArrayList(); + if(nums == null || nums.length == 0) { + return rst; + } + int[][] culmulate = new int[nums.length][2]; + culmulate[0][0] = nums[0]; + culmulate[0][1] = 0; + for (int i = 1; i < nums.length; i++) { + culmulate[i][0] = culmulate[i - 1][0] + nums[i]; + culmulate[i][1] = i; + } + //TEST: + for(int i =0 ; i < nums.length; i++) { + System.out.println("test:" + culmulate[i][0] + " " + culmulate[i][1]); + } + Arrays.sort(culmulate, new CustomComparator()); + for(int i =0 ; i < nums.length; i++) { + System.out.println("sorted:" + culmulate[i][0] + " " + culmulate[i][1]); + } + + int min = Integer.MAX_VALUE; + int start = 0; + int end = 0; + for (int i = 0; i < nums.length - 1; i++) { + int temp = culmulate[i + 1][0] - culmulate[i][0]; + System.out.println(culmulate[i + 1][0] + " minus " + culmulate[i][0] + " = " + temp); + if (temp <= min) { + min = temp; + start = culmulate[i][1]; + end = culmulate[i + 1][1]; + System.out.println("record:" + start + " " + end ); + } + } + System.out.println("min:" + min); + if (start < end) { + rst.add(start + 1); + rst.add(end); + } else { + rst.add(end + 1); + rst.add(start); + } + return rst; + } + + public static void main(String[] args){ + + int[] nums = {6,-4,-8,3,1,7};//{5,10,5,3,2,1,1,-2,-4,3}; + test t = new test(); + ArrayList rst = t.subarraySumClosest(nums); + System.out.println(rst.get(0) + " " + rst.get(1)); + } +} + +*/ + + + + diff --git a/Others/old records/LintCode-Backup/Subarray Sum.java b/Others/old records/LintCode-Backup/Subarray Sum.java new file mode 100644 index 0000000..ab42c31 --- /dev/null +++ b/Others/old records/LintCode-Backup/Subarray Sum.java @@ -0,0 +1,47 @@ +/* +Given an integer array, find a subarray where the sum of numbers is zero. Your code should return the index of the first number and the index of the last number. + +Example +Given [-3, 1, 2, -3, 4], return [0, 2] or [1, 3]. + +Note +There is at least one subarray that it's sum equals to zero. + +Tags Expand +Subarray Hash Table + +Thougths: +Record the sum from (0 ~ a). +Check sum on each index i, when found an existing sum in the hashMap, we are done. +Reason: +If adding all the numbers together, for example if sum[0 ~ a] = -3, ... sum[0 - b] = -3 again, a subarraySum(int[] nums) { + ArrayList rst = new ArrayList(); + if (nums == null || nums.length == 0) { + return rst; + } + int sum = 0; + HashMap map = new HashMap(); + map.put(0, -1); + //we know that sub-array (a,b) has zero sum if SUM(0 ... a-1) = SUM(0 ... b) + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + if (map.containsKey(sum)) { + rst.add(map.get(sum) + 1); + rst.add(i); + return rst; + } + map.put(sum, i); + }//for + return rst; + } +} diff --git a/Others/old records/LintCode-Backup/Subset.java b/Others/old records/LintCode-Backup/Subset.java new file mode 100644 index 0000000..5d47859 --- /dev/null +++ b/Others/old records/LintCode-Backup/Subset.java @@ -0,0 +1,92 @@ +最基本的递归题目。 +坑:记得一开头sort一下 nums。 因为要升序。 + +点: +用level来track到哪一步。最后一level就add into rst +``` +/* +Given a set of distinct integers, return all possible subsets. + +Example +If S = [1,2,3], a solution is: + +[ + [3], + [1], + [2], + [1,2,3], + [1,3], + [2,3], + [1,2], + [] +] +Note +Elements in a subset must be in non-descending order. +The solution set must not contain duplicate subsets. +Challenge +Can you do it in both recursively and iteratively? + +Tags Expand +Recursion Facebook Uber +*/ + +/* + 12.06.2015 recap: +*/ +class Solution { + /** + * @param S: A set of numbers. + * @return: A list of lists. All valid subsets. + */ + public ArrayList> subsets(int[] nums) { + ArrayList> rst = new ArrayList>(); + if (nums == null || nums.length == 0) { + return rst; + } + Arrays.sort(nums); + ArrayList list = new ArrayList(); + helper(rst, list, nums, 0); + + return rst; + } + public void helper(ArrayList> rst, ArrayList list, + int[] nums, int level) { + if (level == nums.length) { + rst.add(new ArrayList(list)); + return; + } + //pick curr num + list.add(nums[level]); + helper(rst, list, nums, level + 1); + list.remove(list.size() - 1); + + //not pick curr num + helper(rst, list, nums, level + 1); + } +} + + + + public ArrayList> subsets(ArrayList source) { + // write your code here + ArrayList> output = new ArrayList>(); + ArrayList newList = new ArrayList(); + Collections.sort(source); + subsetHelper(0, source, newList, output); + return output; + } + + public void subsetHelper(int pos, + ArrayList source, ArrayList newList, + ArrayList> output){ + output.add(new ArrayList(newList)); + + for( int i = pos; i < source.size(); i++){ + newList.add( source.get(i)); + subsetHelper(i+1, source, newList, output); + newList.remove( newList.size() - 1 ); + } + } + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Subsets II.java b/Others/old records/LintCode-Backup/Subsets II.java new file mode 100644 index 0000000..b73756c --- /dev/null +++ b/Others/old records/LintCode-Backup/Subsets II.java @@ -0,0 +1,161 @@ +递归:找准需要pass along的几个数据结构。 + +Iterative: 写一写,用个Queue. +``` +/* +Given a list of numbers that may has duplicate numbers, return all possible subsets + +Have you met this question in a real interview? Yes +Example +If S = [1,2,2], a solution is: + +[ + [2], + [1], + [1,2,2], + [2,2], + [1,2], + [] +] +Note +Each element in a subset must be in non-descending order. +The ordering between two subsets is free. +The solution set must not contain duplicate subsets. +Challenge +Can you do it in both recursively and iteratively? + +Tags Expand +Recursion +*/ + +/* + Thoughts: 12.07.2015 + try to do non-recursive - iterative + + create a queue, initi with []. put [] into rst as well. + Each time pick/not pick curr element: 2 branch: add back into queue, and try to add to rst(if non-exist) + For loop through all elements in S + + Use Queue +*/ + +class Solution { + /** + * @param S: A set of numbers. + * @return: A list of lists. All valid subsets. + */ + public ArrayList> subsetsWithDup(ArrayList S) { + ArrayList> rst = new ArrayList>(); + if (S == null || S.size() == 0) { + return rst; + } + Collections.sort(S); + Queue> queue = new LinkedList>(); + ArrayList list = new ArrayList(); + queue.offer(new ArrayList(list)); + rst.add(new ArrayList(list)); + + for (int i = 0; i < S.size(); i++) { + int num = S.get(i); + int size = queue.size(); + while(size > 0) { + list = queue.poll(); + //Pick + list.add(num); + if (!rst.contains(list)) { + rst.add(new ArrayList(list)); + } + queue.offer(new ArrayList(list)); + list.remove(list.size() - 1); + //Not pick + queue.offer(new ArrayList(list)); + size--; + } + } + return rst; + } +} + + + + +/* + Thoughts: 12.07.2015. + Do regular subset recursion: pick curr or not pick curr, (rst, list, level, S) + Use a HashMap to mark if the cmobination exists already + Recursive. +*/ +class Solution { + /** + * @param S: A set of numbers. + * @return: A list of lists. All valid subsets. + */ + public ArrayList> subsetsWithDup(ArrayList S) { + ArrayList> rst = new ArrayList>(); + if (S == null || S.size() == 0) { + return rst; + } + Collections.sort(S); + ArrayList list = new ArrayList(); + helper(rst, list, S, 0); + + return rst; + } + + public void helper(ArrayList> rst, ArrayList list, + ArrayList S, int level) { + if (!rst.contains(list)) { + rst.add(new ArrayList(list)); + } + if (level == S.size()) { + return; + } + + //pick curr + list.add(S.get(level)); + helper(rst, list, S, level + 1); + list.remove(list.size() - 1); + + //no pick curr + helper(rst, list, S, level + 1); + } +} + + + + + +//Older version, with for loop: + + +class Solution { + /** + * @param S: A set of numbers. + * @return: A list of lists. All valid subsets. + */ + public ArrayList> subsetsWithDup(ArrayList source) { + // write your code here + ArrayList> output = new ArrayList>(); + ArrayList newList = new ArrayList(); + Collections.sort(source); + subsetHelper(0, source, newList, output); + return output; + } + + + public void subsetHelper(int pos, + ArrayList source, ArrayList newList, + ArrayList> output){ + if (!output.contains(newList)){ + output.add(new ArrayList(newList)); + } + + for (int i = pos; i < source.size(); i++){ + newList.add(source.get(i)); + subsetHelper(i + 1, source, newList, output); + newList.remove(newList.size() - 1); + } + + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Subtree.java b/Others/old records/LintCode-Backup/Subtree.java new file mode 100644 index 0000000..f049e3b --- /dev/null +++ b/Others/old records/LintCode-Backup/Subtree.java @@ -0,0 +1,71 @@ +/* +You have two every large binary trees: T1, with millions of nodes, and T2, with hundreds of nodes. Create an algorithm to decide if T2 is a subtree of T1. + +Example +T2 is a subtree of T1 in the following case: + + 1 3 + / \ / +T1 = 2 3 T2 = 4 + / + 4 +T2 isn't a subtree of T1 in the following case: + + 1 3 + / \ \ +T1 = 2 3 T2 = 4 + / + 4 +Note +A tree T2 is a subtree of T1 if there exists a node n in T1 such that the subtree of n is identical to T2. That is, if you cut off the tree at node n, the two trees would be identical. + +Tags Expand +Recursion Binary Tree + +Thoughts: +When T2 == null, reardless of T1 == null or NO, it can always return true; +WHen T2 != null, T1==null returns false; +1. recursively compare the two nodes: if both null, okay; if everything goes well, get deeper into the child nodes. +2. resursively check subtree: check root.left or root.right comparing with T2. + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param T1, T2: The roots of binary tree. + * @return: True if T2 is a subtree of T1, or false. + */ + public boolean isSubtree(TreeNode T1, TreeNode T2) { + if (T2 == null) { + return true; + } else if (T1 == null) { + return false; + } else { + return compare(T1, T2) || isSubtree(T1.left, T2) || isSubtree(T1.right, T2); + } + } + //Recursive compare + public boolean compare(TreeNode node1, TreeNode node2) { + if (node1 == null && node2 == null) { + return true; + } + if (node1 == null || node2 == null){ + return false; + } + if (node1.val != node2.val) { + return false; + } + return compare(node1.left, node2.left) && compare(node1.right, node2.right); + } +} diff --git a/Others/old records/LintCode-Backup/Swap Nodes in Pairs.java b/Others/old records/LintCode-Backup/Swap Nodes in Pairs.java new file mode 100644 index 0000000..2c3116b --- /dev/null +++ b/Others/old records/LintCode-Backup/Swap Nodes in Pairs.java @@ -0,0 +1,61 @@ +swap总是confuse. +画三个block, 1,2,3. 连线。 +``` +/* +Swap Nodes in Pairs + +Given a linked list, swap every two adjacent nodes and return its head. + +Example +Given 1->2->3->4, you should return the list as 2->1->4->3. + +Challenge +Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed. + +Tags Expand +Linked List +*/ + +/* + Thoughts: + 1. swap + 2. move 2 steps, then swap again. + 3. becareful node.next == null, that's the end of list. no swapping. +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ + +public class Solution { + /** + * @param head a ListNode + * @return a ListNode + */ + public ListNode swapPairs(ListNode head) { + if (head == null) { + return head; + } + ListNode dummy = new ListNode(0); + dummy.next = head; + head = dummy; + while (head.next != null && head.next.next != null) { + ListNode n1 = head.next; + ListNode n2 = head.next.next; + + n1.next = n2.next; + n2.next = n1; + n1 = n2; + + head = head.next.next; + } + return dummy.next; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Symmetric Binary Tree.java b/Others/old records/LintCode-Backup/Symmetric Binary Tree.java new file mode 100644 index 0000000..dd7d52c --- /dev/null +++ b/Others/old records/LintCode-Backup/Symmetric Binary Tree.java @@ -0,0 +1,115 @@ +注意Symmetric Binary Tree的例子和定义。 +并不是说左右两个tree相等。 +``` +/* +Given a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center). + +Example + 1 + / \ + 2 2 + / \ / \ +3 4 4 3 +is a symmetric binary tree. + + 1 + / \ + 2 2 + \ \ + 3 3 +is not a symmetric binary tree. + +Challenge +Can you solve it both recursively and iteratively? + +Tags Expand +Binary Tree +*/ + +/* + Thoughts: + verify that left and right tree are identical + A.val == B.val + check(A.left, B.left) + check(A.right, B.right) +*/ +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + +public class Solution { + /** + * @param root, the root of binary tree. + * @return true if it is a mirror of itself, or false. + */ + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + return check(root.left, root.right); + } + + public boolean check(TreeNode A, TreeNode B) { + if (A == null && B == null) { + return true; + } else if (A == null || B == null) { + return false; + } + return A.val == B.val && check(A.left, B.right) && check(A.right, B.left); + } +} + + +//Non-recursive, iterative +/* + Thoughts: + Use 2 stack to hold the child that's needed to compare. + Have to use stack, otherwise, can't iterate through root node. +*/ + +public class Solution { + public boolean isSymmetric(TreeNode root) { + if (root == null) { + return true; + } + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + s1.push(root.left); + s2.push(root.right); + while (!s1.isEmpty() && !s2.isEmpty()) { + TreeNode node1 = s1.pop(); + TreeNode node2 = s2.pop(); + if (node1 == null && node2 == null) { + continue; + } else if (node1 == null || node2 == null) { + return false; + } else if (node1.val != node2.val) { + return false; + } + s1.push(node1.left); + s2.push(node2.right); + s1.push(node1.right); + s2.push(node2.left); + } + + return true; + } +} + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/The Smallest Difference.java b/Others/old records/LintCode-Backup/The Smallest Difference.java new file mode 100644 index 0000000..fd9c4e9 --- /dev/null +++ b/Others/old records/LintCode-Backup/The Smallest Difference.java @@ -0,0 +1,84 @@ +/* +Given two array of integers(the first array is array A, the second array is array B), now we are going to find a element in array A which is A[i], and another element in array B which is B[j], so that the difference between A[i] and B[j] (|A[i] - B[j]|) is as small as possible, return their smallest difference. + + +Example +For example, given array A = [3,6,7,4], B = [2,8,9,3], return 0 + +Challenge +O(n log n) time + +Tags Expand +Two Pointers LintCode Copyright Sort Array +*/ + +/* + Thoughts: + Sort A, B. O(nLogn) + Use smaller array to binarh in longer array. n * logn + +*/ + + +public class Solution { + /** + * @param A, B: Two integer arrays. + * @return: Their smallest difference. + */ + public int smallestDifference(int[] A, int[] B) { + if (A == null || A.length == 0 || B == null || B.length == 0) { + return 0; + } + if (A.length > B.length) { + int[] temp = A; + A = B; + B = temp; + } + Arrays.sort(A); + Arrays.sort(B); + int diff = Integer.MAX_VALUE; + + for (int i = 0; i < A.length; i++) {//10 + int start = 0; + int end = B.length - 1; + int mid; + //Small enhancement + if (B[start] >= A[A.length - 1]) { + return B[start] - A[A.length - 1]; + } + if (A[start] >= B[B.length - 1]) { + return A[start] - B[B.length - 1]; + } + while (start + 1 < end) { + mid = start + (end - start)/2; + if (B[mid] == A[i]) { + return 0; + } else if (mid - 1 >= 0 && B[mid - 1] < A[i] && A[i] < B[mid]) { + diff = Math.min(diff, Math.min(A[i] - B[mid - 1], B[mid] - A[i])); + break; + } else if (mid + 1 < B.length - 1 && B[mid] < A[i] && A[i] < B[mid + 1]) { + diff = Math.min(diff, Math.min(A[i] - B[mid], B[mid + 1] - A[i])); + break; + } else if (B[mid] > A[i]) { + end = mid; + } else { + start = mid; + } + + }//end while + if (start + 1 >= end) { + int min = Math.min(Math.abs(A[i] - B[start]), Math.abs(A[i] - B[end])); + diff = Math.min(diff, min); + } + }//end for + return diff; + } +} + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Top K Frequent Words.java b/Others/old records/LintCode-Backup/Top K Frequent Words.java new file mode 100755 index 0000000..f2f031f --- /dev/null +++ b/Others/old records/LintCode-Backup/Top K Frequent Words.java @@ -0,0 +1,91 @@ +M + +方法1:Brutle force用HashMap存frequency, 用ArrayList存lists of words。最后返回从尾部向前数的k个。 + 注意排序时Collection.sort()的cost是O(nLogk) + + +方法2: Trie && MinHeap屌炸天 + http://www.geeksforgeeks.org/find-the-k-most-frequent-words-from-a-file/ + +``` +/* +Given a list of words and an integer k, return the top k frequent words in the list. + +Example +Given + +[ + "yes", "lint", "code", + "yes", "code", "baby", + "you", "baby", "chrome", + "safari", "lint", "code", + "body", "lint", "code" +] +for k = 3, return ["code", "lint", "baby"]. + +for k = 4, return ["code", "lint", "baby", "yes"], + +Note +You should order the words by the frequency of them in the return list, the most frequent one comes first. If two words has the same frequency, the one with lower alphabetical order come first. + +Challenge +Do it in O(nlogk) time and O(n) extra space. + +Extra points if you can do it in O(n) time with O(k) extra space. + +Tags Expand +Hash Table Heap Priority Queue +*/ + +/* + Attempt1, Thoughts: + Brutle force + HashMap, size n. O(n) + ArrayList> lists: each entry has a list of strings with index as frequency. O(n) + Adding to result String[], do a Collections.sort(), which cause O(nlogk) with a O(n) for loop on top; It becomes O(nLogk)on average. + Return lists' top k. +*/ +public class Solution { + public String[] topKFrequentWords(String[] words, int k) { + String[] rst = new String[k]; + if (words == null || words.length == 0 || k <= 0) { + return rst; + } + + HashMap map = new HashMap(); + ArrayList> lists = new ArrayList>(); + for (int i = 0; i <= words.length; i++) { + lists.add(new ArrayList()); + } + //Fill map + for (int i = 0; i < words.length; i++) { + if (!map.containsKey(words[i])) { + map.put(words[i], 0); + } + map.put(words[i], map.get(words[i]) + 1); + } + //Fill ArrayList + for (Map.Entry entry : map.entrySet()) { + int freqIndex = entry.getValue(); + lists.get(freqIndex).add(entry.getKey()); + } + + int count = 0; + for (int i = lists.size() - 1; i >= 0; i--) { + ArrayList list = lists.get(i); + Collections.sort(list); + for (int j = 0; j < list.size(); j++) { + if (count < k) { + rst[count] = list.get(j); + count++; + } + if (count >= k) { + return rst; + } + } + } + + return rst; + } +} +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Topological Sorting.java b/Others/old records/LintCode-Backup/Topological Sorting.java new file mode 100644 index 0000000..3b4aa87 --- /dev/null +++ b/Others/old records/LintCode-Backup/Topological Sorting.java @@ -0,0 +1,90 @@ +/* +Given an directed graph, a topological order of the graph nodes is defined as follow: + +For each directed edge A -> B in graph, A must before B in the order list. +The first node in the order can be any node in the graph with no nodes direct to it. +Find any topological order for the given graph. + +Example +For graph as follow: + +picture + +The topological order can be: + +[0, 1, 2, 3, 4, 5] +[0, 2, 3, 1, 5, 4] +... +Note +You can assume that there is at least one topological order in the graph. + +Challenge +Can you do it in both BFS and DFS? + +Tags Expand +LintCode Copyright Geeks for Geeks Depth First Search Breadth First Search + +Thoughts: +First idea is Breadth First Search. +1. Find the node which has no parent node: this will be the beginning node. Use a HashMap to map all nodes with children, and whatever not in that map, is a root option. +2. Starting from this node, put all nodes in the queue (breadth-first) +3. process each node in the queue: add to array list + + +Note: All all possible root node (whatever not added into the map) because there could be multiple heads : (. Really need to ask about this if not sure. + +*/ + +/** + * Definition for Directed graph. + * class DirectedGraphNode { + * int label; + * ArrayList neighbors; + * DirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } + * }; + */ +public class Solution { + /** + * @param graph: A list of Directed graph node + * @return: Any topological order for the given graph. + */ + public ArrayList topSort(ArrayList graph) { + ArrayList rst = new ArrayList(); + if (graph == null || graph.size() == 0) { + return graph; + } + //Keep track of all neighbors in HashMap + HashMap map = new HashMap(); + for (DirectedGraphNode node : graph) { + for (DirectedGraphNode neighbor : node.neighbors) { + int keyN = neighbor.label; + if (map.containsKey(keyN)) { + map.put(keyN, map.get(keyN) + 1); + } else { + map.put(keyN, 1); + } + } + } + //BFS: Add root node. Note: + Queue queue = new LinkedList(); + for (DirectedGraphNode node : graph) { + if (!map.containsKey(node.label)) { + queue.offer(node); + rst.add(node); + } + } + //BFS: go through all children + while (!queue.isEmpty()) { + DirectedGraphNode node = queue.poll(); + for (DirectedGraphNode n : node.neighbors) { + int label = n.label; + map.put(label, map.get(label) - 1); + if (map.get(label) == 0) { + rst.add(n); + queue.offer(n); + } + } + } + return rst; + } +} diff --git a/Others/old records/LintCode-Backup/Total Occurrence of Target.java b/Others/old records/LintCode-Backup/Total Occurrence of Target.java new file mode 100644 index 0000000..c48c726 --- /dev/null +++ b/Others/old records/LintCode-Backup/Total Occurrence of Target.java @@ -0,0 +1,101 @@ +想法很简单。写起来有点长。 +找total number of occurance. 首先找first occurance, 再找last occurance. +``` +/* +Total Occurrence of Target + +Given a target number and an integer array sorted in ascending order. Find the total number of occurrences of target in the array. + +Example +Given [1, 3, 3, 4, 5] and target = 3, return 2. + +Given [2, 2, 3, 4, 6] and target = 4, return 1. + +Given [1, 2, 3, 4, 5] and target = 6, return 0. + +Challenge +Time complexity in O(logn) + +Tags Expand +Binary Search +*/ + +/* + Thought: + Similar to find last occurance of the target. Now: find the occurance, jump out. Find front, end occurance index. +*/ +public class Solution { + /** + * @param A an integer array sorted in ascending order + * @param target an integer + * @return an integer + */ + public int totalOccurrence(int[] A, int target) { + if (A == null || A.length == 0) { + return 0; + } + int start = 0; + int end = A.length - 1; + int mid = start + (end - start)/2; + //Find first occurance + int first = 0; + int last = 0; + while (start + 1 < end){ + mid = start + (end - start)/2; + if (A[mid] == target) { + if (mid - 1 >= 0 && A[mid - 1] == target) { + end = mid; + } else { + break; + } + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + if (A[start] == target) { + first = start; + } else if (A[mid] == target){ + first = mid; + } else if (A[end] == target){ + first = end; + } else { + return 0; + } + //If no 2nd occurance, just return + if (mid + 1 < A.length && A[mid + 1] != target) { + return 1; + } + + //Find last occurance + start = first; + last = start + 1; + end = A.length - 1; + while (start + 1 < end){ + mid = start + (end - start)/2; + if (A[mid] == target) { + if (mid + 1 < A.length && A[mid + 1] == target) { + start = mid; + } else { + break; + } + } else if (A[mid] < target) { + start = mid; + } else { + end = mid; + } + } + + if (A[end] == target) { + last = end; + } else if (A[mid] == target){ + last = mid; + } else if (A[start] == target) { + last = start; + } + return last - first + 1; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Trailing Zeros.java b/Others/old records/LintCode-Backup/Trailing Zeros.java new file mode 100644 index 0000000..c28f157 --- /dev/null +++ b/Others/old records/LintCode-Backup/Trailing Zeros.java @@ -0,0 +1,94 @@ +/* +Write an algorithm which computes the number of trailing zeros in n factorial. + +Example +11! = 39916800, so the out should be 2 + +Challenge +O(log N) time + +Tags Expand +Mathematics + +Thoughts: +Attempt1: +Can this problem be converted to : how many 10's to I have? +Loop through n, and check how many 2s, 5s do we have. +For each i, do while loop and count the number of 2s, and 5s in that particular i. + +Note: +5 and 2 makes 10. So don't worry about 10. +Some values will be checked redundantly, so record the ones checked, return the hash value directly. + +Attempt2: +Don't even need to worry about 2's because 2 is definitely more than 5's. Only need to care about 5's. + +How many 5's? n/5. loop (1 ~ n) +However, some number within (1 ~ n) may give more 5's, which for example is: 25 = 5 * 5, double 5's. And 125 = triple 5's. + +In fact count = n / 5 + n / 25 + n / 125 + .... +*/ +class Solution { + /* + * param n: As desciption + * return: An integer, denote the number of trailing zeros in n! + */ + public long trailingZeros(long n) { + if ( n < 5) { + return 0; + } + long count = 0; + for (long i = 5; n / i != 0; i *= 5) { + count += n / i; + } + return count; + } + +} + + + +/* +//Attempt 1: +//This solution exceed time limit, and it's over-complex. 滚粗。 +class Solution { + + private HashMap mapTwo = new HashMap(); + private HashMap mapFive = new HashMap(); + public long trailingZeros(long n) { + if (n < 5) { + return 0; + } + long countFive = 0; + long countTwo = 0; + for (int i = 1; i <= n; i++) { + if (i % 2 == 0) { + countTwo += countExistance(i, 2, mapTwo); + } + if (i % 5 == 0) { + countFive += countExistance(i, 5,mapFive); + } + } + return (countFive < countTwo) ? countFive : countTwo; + } + public long countExistance(long n, long m, HashMap map) { + long temp = n; + long count = 0; + double num = (double)n; + while (num / m == n / m) { + count++; + n = n / m; + num = (double)n; + if (map.containsKey(n)) { + count += map.get(n); + break; + } + } + if (!map.containsKey(temp)) { + map.put(temp, count); + } + return count; + } +}; + +*/ \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Trapping Rain Water II.java b/Others/old records/LintCode-Backup/Trapping Rain Water II.java new file mode 100644 index 0000000..bf459ec --- /dev/null +++ b/Others/old records/LintCode-Backup/Trapping Rain Water II.java @@ -0,0 +1,119 @@ +/* +Trapping Rain Water II +Given n x m non-negative integers representing an elevation map 2d where the area of each cell is 1 x 1, compute how much water it is able to trap after raining. + + +Example +Given 5*4 matrix + +[12,13,0,12] +[13,4,13,12] +[13,8,10,12] +[12,13,12,12] +[13,13,13,13] +return 14. + +Tags Expand + +LintCode Copyright Heap Matrix + +*/ + +/* +Thoughts: same idea as the trap Rain Water I. +Since this is not 1-way run through a 1D array (2D array can go 4 directions...), need to mark visted spot. + +Use PriorityQueue, sort lowest on top, because the lowest surroundings determines the best we can get. + +Bukkit theory: the lowest bar determines the height of the bukkit water. So, we always process the lowest first. +Therefore, we use a min-heap, a natural order priorityqueue based on height. + +Note: when adding a new block into the queue, comparing with the checked origin, we still want to add the higher height into queue. +(The high bar will always exist and hold the bukkit.) + +Step: +1. Create Cell (x,y,h) +2. Priorityqueue on Cell of all 4 borders +3. Process each element in queue, and add surrounding blocks into queue. +4. Mark checked block + + +*/ + +public class Solution { + class Cell { + int x; + int y; + int h; + public Cell(int x, int y, int height) { + this.x = x; + this.y = y; + this.h = height; + } + } + /** + * @param heights: a matrix of integers + * @return: an integer + */ + public int trapRainWater(int[][] heights) { + if (heights == null || heights.length == 0 || heights[0].length == 0) { + return 0; + } + + PriorityQueue queue = new PriorityQueue(1, new Comparator(){ + public int compare(Cell A, Cell B) { + return A.h - B.h; + } + }); + int n = heights.length; + int m = heights[0].length; + boolean[][] visited = new boolean[n][m]; + + //LEFT-RIGHT + for (int i = 0; i < n; i++) { + visited[i][0] = true; + visited[i][m - 1] = true; + queue.offer(new Cell(i, 0, heights[i][0])); + queue.offer(new Cell(i, m - 1, heights[i][m - 1])); + } + //TOP-BOTTOM + for (int i = 0; i < m; i++) { + visited[0][i] = true; + visited[n - 1][i] = true; + queue.offer(new Cell(0, i, heights[0][i])); + queue.offer(new Cell(n - 1, i, heights[n - 1][i])); + } + + int[] xs = {0, 0, 1, -1}; + int[] ys = {1, -1, 0, 0}; + int sum = 0; + while (!queue.isEmpty()) { + Cell cell = queue.poll(); + for (int i = 0; i < 4; i++) { + int nx = cell.x + xs[i]; + int ny = cell.y + ys[i]; + if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) { + visited[nx][ny] = true; + sum += Math.max(0, cell.h - heights[nx][ny]); + queue.offer(new Cell(nx, ny, Math.max(heights[nx][ny], cell.h))); + } + } + }//end while + return sum; + } +}; + + + + + + + + + + + + + + + diff --git a/Others/old records/LintCode-Backup/Trapping Rain Water.java b/Others/old records/LintCode-Backup/Trapping Rain Water.java new file mode 100644 index 0000000..cf83d97 --- /dev/null +++ b/Others/old records/LintCode-Backup/Trapping Rain Water.java @@ -0,0 +1,104 @@ +2 Pointers, +双面夹击:找中间最大bar,两面往中心扫 + +``` +/* +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. + +Example +Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6. + +Challenge +O(n) time and O(1) memory + +O(n) time and O(n) memory is also acceptable. + +Tags Expand +Two Pointers Forward-Backward Traversal Array + +Related Problems Expand +Medium Container With Most Water + +LeetCode: +Tags: Array, Stack, Two Pointers +Similar Problems: (M) Container With Most Water, (M) Product of Array Except Self + + +*/ + +/* +Thoughts: +1. Find max's index, and use this index as the central pivot. (WHY? because highest bar can hold any volumn of water) +2. Process left and right separately. + a. assume each height jump fills that increased height of volumn. that is, if increased by r rows, add r rows of water into sum + b. all the black blocks (stones) should be minus from the sum on each index. +O(n) on finding the max. +O(n/2) for both left and right. +Total 2*O(n) = O(n) + +*/ + +//O(n) + +public class Solution { + /** + * @param heights: an array of integers + * @return: a integer + */ + public int trapRainWater(int[] heights) { + if (heights == null || heights.length == 0) { + return 0; + } + + int max = 0; + int maxIndex = 0; + int sum = 0; + int prev = 0; + for (int i = 0; i < heights.length; i++) { + if (heights[i] > max) { + max = heights[i]; + maxIndex = i; + } + } + + //Process left + for (int i = 0; i < maxIndex; i++) { + if (heights[i] > prev) { + sum += (maxIndex - i) * (heights[i] - prev); + prev = heights[i]; + } + sum -= heights[i]; + } + + //Process right: + prev = 0; + for (int i = heights.length - 1; i > maxIndex; i--) { + if (heights[i] > prev) { + sum += (i - maxIndex) * (heights[i] - prev); + prev = heights[i]; + } + sum -= heights[i]; + } + + return sum; + } +} + + + + + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Triangle Count.java b/Others/old records/LintCode-Backup/Triangle Count.java new file mode 100644 index 0000000..4a9f57a --- /dev/null +++ b/Others/old records/LintCode-Backup/Triangle Count.java @@ -0,0 +1,62 @@ +/* +Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find? + +Example +Given array S = [3,4,6,7], return 3. They are: + +[3,4,6] +[3,6,7] +[4,6,7] +Given array S = [4,4,4,4], return 4. They are: + +[4(1),4(2),4(3)] +[4(1),4(2),4(4)] +[4(1),4(3),4(4)] +[4(2),4(3),4(4)] +Tags Expand +Two Pointers LintCode Copyright +*/ + +/* +Thoughts: +Pick 3 integers that fits the condition: +A + B > C +B + C > A +A + C > B +If we sort the input, then we know A <= B <= C, so we can remove 2 conditoins above and only have: +A + B > C +That is, Pick one C, and pick two integers A,B in front. Similar to TWO SUM II. +Have a fixed C as target, and find A + B > target in the remaining array on left of C. +How about just use 2 pointers left, right, and compare with a C (s[i] in for loop) +Time: O(n^2) + +Note: don't forget to sort +*/ + +public class Solution { + /** + * @param S: A list of integers + * @return: An integer + */ + public int triangleCount(int S[]) { + if (S == null || S.length == 0) { + return 0; + } + Arrays.sort(S); + int count = 0; + for (int i = 0; i < S.length; i++) { + int left = 0; + int right = i - 1; //at least 1 step left from C + while (left < right){ + if (S[left] + S[right] > S[i]) { + count += (right - left); + right--; + } else {//(S[left] + S[right] <= S[i]) + left++; + } + } + } + return count; + } +} + diff --git a/Others/old records/LintCode-Backup/Tweaked Identical Binary Tree.java b/Others/old records/LintCode-Backup/Tweaked Identical Binary Tree.java new file mode 100644 index 0000000..cf00367 --- /dev/null +++ b/Others/old records/LintCode-Backup/Tweaked Identical Binary Tree.java @@ -0,0 +1,68 @@ +/* +Check two given binary trees are identical or not. Assuming any number of tweaks are allowed. A tweak is defined as a swap of the children of one node in the tree. + +Have you met this question in a real interview? Yes +Example + 1 1 + / \ / \ + 2 3 and 3 2 + / \ +4 4 +are identical. + + 1 1 + / \ / \ + 2 3 and 3 4 + / \ +4 2 +are not identical. + +Note +There is no two nodes with the same value in the tree. + +Challenge +O(n) time + +Tags Expand +Binary Tree +*/ + +/* + check isTweakedIdentical(a.left, b.right); + + corner case: if both null, true; + if one null, false +*/ +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @param a, b, the root of binary trees. + * @return true if they are tweaked identical, or false. + */ + public boolean isTweakedIdentical(TreeNode a, TreeNode b) { + if (a == null || b == null) { + return a == null && b == null; + } + if (a.val != b.val) { + return false; + } + return (isTweakedIdentical(a.left, b.left) && isTweakedIdentical(a.right, b.right)) + || (isTweakedIdentical(a.left, b.right) && isTweakedIdentical(a.right, b.left)); + } +} + + + + + + diff --git a/Others/old records/LintCode-Backup/Two Lists Sum.java b/Others/old records/LintCode-Backup/Two Lists Sum.java new file mode 100644 index 0000000..62f071a --- /dev/null +++ b/Others/old records/LintCode-Backup/Two Lists Sum.java @@ -0,0 +1,58 @@ +/* +You have two numbers represented by a linked list, where each node contains a single digit.The digits are stored in reverse order, such that the 1’s digit is at the head of the list.Write a function that adds the two numbers and returns the sum as a linked list. + +Example +Given two lists, 3->1->5->null and 5->9->2->null, return 8->0->8->null + +Tags Expand +Linked List Backtracking +//TODO: check 9chapter solution +Thinking process: +Simply add 2 lists’ values together. +Handle the carrier +Use dummy node at beginning. +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param l1: the first list + * @param l2: the second list + * @return: the sum list of l1 and l2 + */ + public ListNode addLists(ListNode l1, ListNode l2) { + ListNode rst = new ListNode(0); + ListNode dummy = rst; + int carrier = 0; + //while + while (l1 != null || l2 != null) { + if (l1 != null) { + carrier += l1.val; + l1 = l1.next; + } + if (l2 != null) { + carrier += l2.val; + l2 = l2.next; + } + rst.next = new ListNode(carrier % 10); + carrier = carrier / 10; + rst = rst.next; + } + //check the carrier + if (carrier == 1) { + rst.next = new ListNode(1); + } + return dummy.next; + } +} + diff --git a/Others/old records/LintCode-Backup/Two Strings Are Anagrams.java b/Others/old records/LintCode-Backup/Two Strings Are Anagrams.java new file mode 100644 index 0000000..88b09b4 --- /dev/null +++ b/Others/old records/LintCode-Backup/Two Strings Are Anagrams.java @@ -0,0 +1,103 @@ +E + +方法1:char ascii 用count[256] +坑:不要想象这个是个26letter lowercase. may not be true. + +方法2: 若是其他字符encoding, 而不只是utf16-encoding (java char)? +那么就继续用string去做 + +``` +/* +Write a method anagram(s,t) to decide if two strings are anagrams or not. + +Example +Given s="abcd", t="dcab", return true. + +Challenge +O(n) time, O(1) extra space + +Tags Expand +String Cracking The Coding Interview + +*/ +/* + Recap 12.09.2015 + O(n) time: cannot Arrays.sort() + O(1) extra space: cannot convert to char array. But we can use a count[256] to count the occuranceo of letters. + + do 1 for loop: + + occurance index + - occurance index + + border cases: + null: false. + both length() == 0, true + length() not equal: false + + don't assume all lower case. + there are ' ' space, so it can't be just 26 letters. make it 256 +*/ +public class Solution { + public boolean anagram(String s, String t) { + if (s == null || t == null) { + return false; + } else if (s.length() != t.length()) { + return false; + } else if (s.length() == 0 && t.length() == 0) { + return true; + } + int[] count = new int[256]; + for (int i = 0; i < s.length(); i++) { + count[s.charAt(i)]++; + count[t.charAt(i)]--; + } + for (int num : count) { + if (num != 0) { + return false; + } + } + return true; + } +}; + + +/* +What if it's not just ascii code, maybe uni-code? +Then the character (utf16-encoding) may not be enough. So we use String here. +*/ + +//check length. compare +public class Solution { + public boolean isAnagram(String s, String t) { + if (s == null || t == null || s.length() != t.length()) { + return false; + } + if (s.equals(t)) { + return true; + } + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + String ss = s.substring(i, i + 1); + String tt = t.substring(i, i + 1); + if (!map.containsKey(ss)) { + map.put(ss, 0); + } + map.put(ss, map.get(ss) + 1); + if (!map.containsKey(tt)) { + map.put(tt, 0); + } + map.put(tt, map.get(tt) - 1); + } + + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() != 0) { + return false; + } + } + + return true; + } +} + + +``` \ No newline at end of file diff --git a/Java/Two Sum II.java b/Others/old records/LintCode-Backup/Two Sum II.java similarity index 100% rename from Java/Two Sum II.java rename to Others/old records/LintCode-Backup/Two Sum II.java diff --git a/Others/old records/LintCode-Backup/Ugly Number.java b/Others/old records/LintCode-Backup/Ugly Number.java new file mode 100644 index 0000000..026c1d7 --- /dev/null +++ b/Others/old records/LintCode-Backup/Ugly Number.java @@ -0,0 +1,63 @@ +/* +Ugly number is a number that only have factors 3, 5 and 7. + +Design an algorithm to find the Kth ugly number. The first 5 ugly numbers are 3, 5, 7, 9, 15 ... + +Example +If K=4, return 9. + +Challenge +O(K log K) or O(K) time. + +Tags Expand +LintCode Copyright Priority Queue + +Thoughts: +Every level it's like: +3 5 7 +3 3,5 3,5,7 + +Use a priority queue to keep track. +Use a for loop to keep calculating the target number, and return it at the end + +Note: +Why not offer 3,5, 7 in first if statement? (Which is my original thought). Maybe, we want to limit the number of offers in 3's case, in case some 3's cases becomes bigger than 5's case. That, will accidentally prevent the program to check on 5's. +Therefore, leave 3,5,7 cases till 7's . + +*/ + +class Solution { + /** + * @param k: The number k. + * @return: The kth prime number as description. + */ + public long kthPrimeNumber(int k) { + if (k == 0) { + return 0; + } + PriorityQueue queue = new PriorityQueue(); + queue.offer((long)3); + queue.offer((long)5); + queue.offer((long)7); + long num = 0; + for (int i = 0; i < k; i++) { + num = queue.poll(); + if (num % 3 == 0) { + queue.offer(num * 3); + } else if (num % 5 == 0) { + queue.offer(num * 3); + queue.offer(num * 5); + } else if (num % 7 == 0) { + queue.offer(num * 3); + queue.offer(num * 5); + queue.offer(num * 7); + } + } + return num; + } +}; + + +/* +Can use DP as well:http://blog.welkinlan.com/2015/07/28/ugly-number-lintcode-java/ +*/ \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Unique Binary Search Tree II.java b/Others/old records/LintCode-Backup/Unique Binary Search Tree II.java new file mode 100644 index 0000000..b7ec9a6 --- /dev/null +++ b/Others/old records/LintCode-Backup/Unique Binary Search Tree II.java @@ -0,0 +1,61 @@ +/* +Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. + +Example +Given n = 3, your program should return all 5 unique BST's shown below. + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 +Tags Expand +Dynamic Programming Depth First Search + +Thinking process: +- For a BST, root can be any node from node(1) to node(n). +- For each root, left nodes has mutiple forms of BST, and right node has mutiple forms of BST. +- For each root node, divide and conquer left / right +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @paramn n: An integer + * @return: A list of root + */ + public List generateTrees(int n) { + return generate(1, n); + } + public ArrayList generate(int start, int end) { + ArrayList rst = new ArrayList(); + if (start > end) { + rst.add(null); + return rst; + } + for (int i = start; i <= end; i++){ + ArrayList left = generate(start, i - 1); + ArrayList right = generate(i + 1, end); + for (TreeNode l : left) { + for (TreeNode r : right) { + TreeNode root = new TreeNode(i); + root.left = l; + root.right = r; + rst.add(root); + } + } + } + return rst; + } +} + diff --git a/Others/old records/LintCode-Backup/Unique Binary Search Tree.java b/Others/old records/LintCode-Backup/Unique Binary Search Tree.java new file mode 100644 index 0000000..5d373b4 --- /dev/null +++ b/Others/old records/LintCode-Backup/Unique Binary Search Tree.java @@ -0,0 +1,42 @@ +/* +Given n, how many structurally unique BST's (binary search trees) that store values 1...n? + + + +Example +Given n = 3, there are a total of 5 unique BST's. + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 +Tags Expand +Catalan Number Dynamic Programming + +Thinking proces: +Knowing what is Catalan number. +C(n+1) = SUM(C(i)*C(n-i)) +OR: C(n) = SUM(C(i)*C(n-i-1)). +*/ + +public class Solution { + /** + * @paramn n: An integer + * @return: An integer + */ + public int numTrees(int n) { + if (n <= 1) { + return 1; + } + int[] count = new int[n + 1]; + count[0] = 1; + count[1] = 1; + for (int i = 2; i < n + 1; i++) { + for (int j = 0; j < i; j++) { + count[i] += count[j] * count[i - j - 1]; + } + } + return count[n]; + } +} diff --git a/Others/old records/LintCode-Backup/Unique Characters.java b/Others/old records/LintCode-Backup/Unique Characters.java new file mode 100644 index 0000000..6e4c03c --- /dev/null +++ b/Others/old records/LintCode-Backup/Unique Characters.java @@ -0,0 +1,74 @@ +不用额外data structure, O(n^2), double for loop. +用hashSet, space O(n), time O(n) +``` +/* +Implement an algorithm to determine if a string has all unique characters. + +Example +Given "abc", return true. + +Given "aab", return false. + +Challenge +What if you can not use additional data structures? + +Tags Expand +String Cracking The Coding Interview Array +*/ + +/* + Thought: + do it without hash set. + Can do a double-for loop, check from i~j, if str[i] exist later in the string. + O(n^2) +*/ + +public class Solution { + /** + * @param str: a string + * @return: a boolean + */ + public boolean isUnique(String str) { + if (str == null || str.length() == 0) { + return true; + } + for (int i = 0; i < str.length(); i++) { + for (int j = i + 1; j < str.length(); j++) { + if (str.charAt(i) == str.charAt(j)) { + return false; + } + } + } + return true; + } +} + + + +/* + Thought: + 1st, write hasset, there you go. +*/ +public class Solution { + /** + * @param str: a string + * @return: a boolean + */ + public boolean isUnique(String str) { + if (str == null || str.length() == 0) { + return true; + } + HashSet set = new HashSet(); + for (int i = 0; i < str.length(); i++) { + if (!set.contains(str.charAt(i))) { + set.add(str.charAt(i)); + } else { + return false; + } + }//end for + + return true; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Unique Path.java b/Others/old records/LintCode-Backup/Unique Path.java new file mode 100644 index 0000000..90e5be2 --- /dev/null +++ b/Others/old records/LintCode-Backup/Unique Path.java @@ -0,0 +1,106 @@ +/* +A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). + +The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). + +How many possible unique paths are there? + +Note +m and n will be at most 100. + +Example +1,1 1,2 1,3 1,4 1,5 1,6 1,7 +2,1 +3,1 3,7 + +Above is a 3 x 7 grid. How many possible unique paths are there? + +Tags Expand +Array Dynamic Programming + +Thinking process: +f[x][y]: want to find out all possible path +To get to f[m][m] from f[m-1][n-1] has 2 way: f[m-1][n] or f[m][n-1]. +After found 'f[m-1][n-1]', store it to a Hashmap with the #path. +Every node pair (x,y) should have 1 solution. +Recursively add up to (0,0), will find out the total path. + +1. Own solution: user HashMap to memorize +*/ + +public class Solution { + /** + * @param n, m: positive integer (1 <= n ,m <= 100) + * @return an integer + */ + private int m,n; + public int uniquePaths(int m, int n) { + if (m <= 1 || n <= 1) { + return 1; + } + this.m = m; + this.n = n; + HashMap, Integer> his = + new HashMap, Integer>(); + int right = helper(0, 1, his); + int down = helper(1, 0, his); + return right + down; + } + + public int helper(int x, int y, HashMap, Integer> his) { + ArrayList pair = new ArrayList(); + pair.add(x); + pair.add(y); + if (his.containsKey(pair)) { + return his.get(pair); + } + if (x >= this.m -1 || y >= this.n - 1) { + his.put(pair, 1); + return his.get(pair); + } + int right = helper(x, y + 1, his); + int down = helper(x + 1, y, his); + his.put(pair, right + down); + return his.get(pair); + } +} + +/* + +2. 9Chapter solution +Thinking process: +1. Assume (r,c) where r>=1, c>=1. Any node (r,c) has 2 ways to get to: (r-1, c) from top, or (r,c-1) from left-side. +2. (r-1, c) and (r,c-1) stores the possible paths to get to them +3. (r,c) = (r-1, c) + (r,c-1) +4. Initialize the top-row and left-column to be 1: Assuming landing on any initial node has path # of 1. +5. From top-bottom traverse +*/ + +public class Solution { + /** + * @param n, m: positive integer (1 <= n ,m <= 100) + * @return an integer + */ + //Traverse + public int uniquePaths(int m, int n) { + if (m <= 1 || n <= 1) { + return 1; + } + int[][] matrix = new int[m][n]; + //Initialize + for (int i = 0; i < m; i++) { + matrix[i][0] = 1; + } + for (int i = 0; i < n; i++) { + matrix[0][i] = 1; + } + //Traverse + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + matrix[i][j] = matrix[i - 1][j] + matrix[i][j - 1]; + } + } + return matrix[m - 1][n - 1]; + } +} + diff --git a/Others/old records/LintCode-Backup/Unique Paths II.java b/Others/old records/LintCode-Backup/Unique Paths II.java new file mode 100644 index 0000000..51d7ef3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Unique Paths II.java @@ -0,0 +1,70 @@ +/* +Follow up for "Unique Paths": + +Now consider if some obstacles are added to the grids. How many unique paths would there be? + +An obstacle and empty space is marked as 1 and 0 respectively in the grid. + +Note +m and n will be at most 100. + +Example +For example, +There is one obstacle in the middle of a 3x3 grid as illustrated below. + +[ + [0,0,0], + [0,1,0], + [0,0,0] +] +The total number of unique paths is 2. + +Tags Expand +Array Dynamic Programming + +Thinking process: +1. Still use an extra matrix to count possible paths. +2. When initializing, skip block if it's obstacle (break the for loop, basically skip this row/col) +3. When evaluating paths, skip block if it's obstacle (save current spot's path as 0, means no path through this point). +4. Note: At evaluating double-for loop, we cannot use break, because we still need to evaluate using upper/left block. Hence we set the obstacle = 0. +*/ + +public class Solution { + /** + * @param obstacleGrid: A list of lists of integers + * @return: An integer + */ + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + if (obstacleGrid == null || obstacleGrid.length == 0 || obstacleGrid[0].length == 0) { + return 0; + } + int row = obstacleGrid.length; + int col = obstacleGrid[0].length; + int[][] matrix = new int[row][col]; + for (int i = 0; i < row; i++) { + if (obstacleGrid[i][0] == 1) { + break; + } else { + matrix[i][0] = 1; + } + } + for (int j = 0; j < col; j++) { + if (obstacleGrid[0][j] == 1) { + break; + } else { + matrix[0][j] = 1; + } + } + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + if (obstacleGrid[i][j] == 1) { + matrix[i][j] = 0; + } else { + matrix[i][j] = matrix[i - 1][j] + matrix[i][j - 1]; + } + } + } + return matrix[row - 1][col - 1]; + } +} + diff --git a/Others/old records/LintCode-Backup/Update Bits.java b/Others/old records/LintCode-Backup/Update Bits.java new file mode 100644 index 0000000..cdd2b5b --- /dev/null +++ b/Others/old records/LintCode-Backup/Update Bits.java @@ -0,0 +1,41 @@ +/* +Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j) + + + +Example +Given N = (10000000000)2, M = (10101)2, i = 2, j = 6 + +return N = (10001010100)2 + +Challenge +Minimum number of operations? + +Tags Expand +Cracking The Coding Interview Bit Manipulation Binary Representation + +Thinking process: +Create a mask: xxxx000000xxxx. +Trick part: when it encounters negative number or dealing with index at edge index = 31, it starts having issue. Interesting fix: use long for masks. +*/ + +class Solution { + /** + *@param n, m: Two integer + *@param i, j: Two bit positions + *return: An integer + */ + public int updateBits(int n, int m, int i, int j) { + //Create mask: xxx00000xxx + long rightMask = ~0 >> i; + rightMask = ~(rightMask << i);// 00000xxx + long leftMask = ~0 >> (j + 1); + leftMask = leftMask << (j + 1);//xxxxx00000000 + long mask = leftMask | rightMask;//xxx00000xxx + n = (int) (n & mask); + n = (int) (n | (m << i)); + return n; + } +} + + diff --git a/Others/old records/LintCode-Backup/Valid Palindrome.java b/Others/old records/LintCode-Backup/Valid Palindrome.java new file mode 100644 index 0000000..88a81a9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Valid Palindrome.java @@ -0,0 +1,61 @@ +注意如何滤过: alphanumeric +``` +/* +Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. + +Example +"A man, a plan, a canal: Panama" is a palindrome. + +"race a car" is not a palindrome. + +Note +Have you consider that the string might be empty? This is a good question to ask during an interview. + +For the purpose of this problem, we define empty string as valid palindrome. + +Challenge +O(n) time without extra memory. + +Tags Expand +String Two Pointers +*/ +/* +Thoughts: +Pointer from front to end. Front char has to equal end char. +For loop check till s.length()/2. +If even, for example, s.length() == 4, i will be [0 ~ 1]. +If odd, for example, s.length() == 5, i will be [0 ~ 1]. And inddex 2 itself stands out, and won't hurt palindrome. +*/ + +public class Solution { + /** + * @param s A string + * @return Whether the string is a valid palindrome + */ + public boolean isPalindrome(String s) { + if (s == null || s.length() == 0) { + return true; + } + int start = 0; + int end = s.length() - 1; + s = s.toLowerCase(); + while (start < end) { + while (start < s.length() && + (s.charAt(start) < '0' || (s.charAt(start) > '9' && s.charAt(start) < 'a') || s.charAt(start) > 'z') ) { + start++; + } + while (end >= 0 && + (s.charAt(end) < '0' || (s.charAt(end) > '9' && s.charAt(end) < 'a') || s.charAt(end) > 'z')) { + end--; + } + if (start < end && s.charAt(start) != s.charAt(end)) { + return false; + } + start++; + end--; + } + return true; + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Valid Parentheses.java b/Others/old records/LintCode-Backup/Valid Parentheses.java new file mode 100644 index 0000000..8dd1ded --- /dev/null +++ b/Others/old records/LintCode-Backup/Valid Parentheses.java @@ -0,0 +1,104 @@ +E + +剥皮过程。解铃还须系铃人 +左边的外皮'{['在stack底部 +右边的外皮应该和stack顶上的左外皮一一对应 + + + +``` +/* +Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. + +Example +The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. + +Tags Expand +Stack +*/ + +//02.04.2015 Recap +//lock will be unlocked by the same key +//put in stack. when '),],}' appears, check stack.top() to make sure they are good match +public class Solution { + public boolean isValid(String s) { + if (s == null || s.length() == 0) { + return true; + } + if (s.length() % 2 != 0) { + return false; + } + Stack stack = new Stack(); + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } else if (c ==')' || c == ']' || c == '}') { + if (stack.isEmpty()) { + return false; + } + char front = stack.pop(); + if (c == ')' && front != '(') { + return false; + } + if (c == ']' && front != '[') { + return false; + } + if (c == '}' && front != '{') { + return false; + } + } else { + return false; + } + } + + return stack.isEmpty(); + } +} + + +/* + Thoughts: + Did this on Leetcode. Think about how do we naturally check it? + Use stack to hold '({[', and check against peek() every time on next element. + Check it nagativly. If all pass, return true; + + Note: + If stack is not cleanup, then it's false. +*/ +public class Solution { + /** + * @param s A string + * @return whether the string is a valid parentheses + */ + public boolean isValidParentheses(String s) { + if (s == null || s.length() < 2) { + return false; + } + Stack stack = new Stack(); + char[] arr = s.toCharArray(); + for (int i = 0; i < arr.length; i++) { + if (arr[i] == '(' || arr[i] == '[' || arr[i] == '{') { + stack.push(arr[i]); + } else if (arr[i] == ')' || arr[i] == ']' || arr[i] == '}') { + if (stack.isEmpty()) { + return false; + } else { + char c = stack.pop(); + if ((c == '(' && arr[i] == ')') || + (c == '[' && arr[i] == ']') || + (c == '{' && arr[i] == '}')) { + continue; + } + return false; + } + } else { + return false; + } + } + return stack.isEmpty(); + } +} + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Valid Sudoku.java b/Others/old records/LintCode-Backup/Valid Sudoku.java new file mode 100644 index 0000000..4988597 --- /dev/null +++ b/Others/old records/LintCode-Backup/Valid Sudoku.java @@ -0,0 +1,90 @@ +好像没啥技术含量. 做就行了。 +validate block的时候虽然看到了4层for.其实也就是n^2. +``` +/* +Determine whether a Sudoku is valid. + +The Sudoku board could be partially filled, where empty cells are filled with the character .. + + +Example +The following partially filed sudoku is valid. + +Valid Sudoku (Image can display here: http://www.lintcode.com/en/problem/valid-sudoku/#) + +Note +A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated. + +Clarification +What is Sudoku? + +http://sudoku.com.au/TheRules.aspx +https://zh.wikipedia.org/wiki/%E6%95%B8%E7%8D%A8 +https://en.wikipedia.org/wiki/Sudoku +http://baike.baidu.com/subview/961/10842669.htm +Tags Expand +Matrix +*/ + +/* + Thoughts: + Each row/col/block can only 1 ~ 9, no duplicates + Use HashSet, reinitiate 3 times. + traverse row, col, block + O(n^2) +*/ + +class Solution { + /** + * @param board: the board + @return: wether the Sudoku is valid + */ + public boolean isValidSudoku(char[][] board) { + if (board == null || board.length == 0 || board[0].length == 0 || board.length != board[0].length) { + return false; + } + HashSet row,col,block; + int n = board.length; + + for (int i = 0; i < n; i++) { + row = new HashSet(); + col = new HashSet(); + for (int j = 0; j < n; j++) { + //Check row + if (!row.contains(board[i][j])) { + row.add(board[i][j]); + } else if (board[i][j] != '.'){ + return false; + } + //Check col + if (!col.contains(board[j][i])) { + col.add(board[j][i]); + } else if (board[j][i] != '.'){ + return false; + } + } + } + + for (int i = 0; i < n; i+=3) { + for (int j = 0; j < n; j+=3) { + block = new HashSet(); + //Check block + for (int k = 0; k < 3; k++) { + for (int h = 0; h < 3; h++) { + if (!block.contains(board[i+k][j+h])) { + block.add(board[i+k][j+h]); + } else if (board[i+k][j+h] != '.'){ + return false; + } + } + } + } + + } + + + return true; + } +}; + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Validate Binary Search Tree.java b/Others/old records/LintCode-Backup/Validate Binary Search Tree.java new file mode 100644 index 0000000..1942660 --- /dev/null +++ b/Others/old records/LintCode-Backup/Validate Binary Search Tree.java @@ -0,0 +1,74 @@ +M + +查看每个parent-child关系。同时把root level上面传下来max,min界限定住。 + +``` +/* +29% Accepted +Given a binary tree, determine if it is a valid binary search tree (BST). + +Assume a BST is defined as follows: + +The left subtree of a node contains only nodes with keys less than the node's key. +The right subtree of a node contains only nodes with keys greater than the node's key. +Both the left and right subtrees must also be binary search trees. +Example +An example: + + 1 + / \ + 2 3 + / + 4 + \ + 5 +The above binary tree is serialized as "{1,2,3,#,#,4,#,#,5}". + +Tags Expand +Tree Binary Tree Binary Search Tree + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ + +//recursively check if tree are BST, && them all + +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode(int x) { val = x; } + * } + */ +public class Solution { + public boolean isValidBST(TreeNode root) { + return helper(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean helper(TreeNode root, long min, long max) { + if (root == null) { + return true; + } + if (root.val < max && root.val > min && + helper(root.left, min, root.val) && + helper(root.right, root.val, max)) { + return true; + } + return false; + } +} + + +``` \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Wood Cut.java b/Others/old records/LintCode-Backup/Wood Cut.java new file mode 100644 index 0000000..0d862d3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Wood Cut.java @@ -0,0 +1,71 @@ +/* +Given n pieces of wood with length L[i] (integer array). Cut them into small pieces to guarantee you could have equal or more than k pieces with the same length. What is the longest length you can get from the n pieces of wood? Given L & k, return the maximum length of the small pieces. + +Note +You couldn't cut wood into float length. + +Example +For L=[232, 124, 456], k=7, return 114. + +Challenge +O(n log Len), where Len is the longest length of the wood. + +Tags Expand +Binary Search + +Thinking process: +Take the largest item. +Priorities: +1. Have to get calculatedK >= givenK +2. Meanwhile, want to maximize the smal piece. + +One thing not clear: do we have to use the given small piece? If we have to, we need to concern about the shortest wood piece. See commentted-out part +In this problem, however, we can abandon the small pieces, as long as the max_small_pieces can allow calculatedK >= givenK. + +Use binary search on the largest item: +1. if calculatedK < givenK: end = mid; +2. If calculated >= givenK, move start = mid as much as possible, which gives maximized small piece. + +*/ + + +public class Solution { + /** + *@param L: Given n pieces of wood with length L[i] + *@param k: An integer + *return: The maximum length of the small pieces. + */ + public int woodCut(int[] L, int k) { + if (L == null || L.length == 0 || k < 0) { + return 0; + } + if (L.length == 1) { + return L[0] / (L[0] / k); + } + Arrays.sort(L); + int start = 0; + int end = L[L.length - 1]; + int mid = 0; + int max = 0; + // int min = L[0]; + while (start + 1 < end) { + mid = start + (end - start) / 2; + //if (mid > min) { + // end = mid; + // } else { + int count = 0; + for (int i : L) { + count += i / mid; + } + if (count < k) { + end = mid; + } else { + start = mid; + max = mid; + } + //} + }//end while + return max; + } +} + diff --git a/Others/old records/LintCode-Backup/Word Break.java b/Others/old records/LintCode-Backup/Word Break.java new file mode 100644 index 0000000..1ff9ff8 --- /dev/null +++ b/Others/old records/LintCode-Backup/Word Break.java @@ -0,0 +1,94 @@ +/* +Given a string s and a dictionary of words dict, determine if s can be break into a space-separated sequence of one or more dictionary words. + +Example +Given s = "lintcode", dict = ["lint", "code"]. + +Return true because "lintcode" can be break as "lint code". + +Tags Expand +String Dynamic Programming + +*/ +/* +Attemp3: +Optimize attempt2: If the input s is super long, but Dict does not have that long string, then we should avoid that case, so to save time. That is, check dict's strings' max length, and incldue that in 2nd-level for loop + +j: last word's length, range from 0 to i. +[i - j]: the first index of current word +rst[i - j]: if s[i ~ j] returns true +s.substring(i - j, i): if s[i-j position to i position] is in dict + +Note: use maxLength to optimize the solution. + +*/ + +public class Solution { + public boolean wordBreak(String s, Set dict) { + if (s == null || dict.contains(s)) { + return true; + } + boolean[] rst = new boolean[s.length() + 1]; + rst[0] = true; + int maxLength = calMaxLength(dict); + for (int i = 0; i <= s.length(); i++) { + for (int j = 0; j <= i && j <= maxLength; j++) { + if (rst[i - j] && dict.contains(s.substring(i - j, i))) { + rst[i] = true; + break; + } + } + } + return rst[s.length()]; + } + + public int calMaxLength(Set dict) { + int length = 0; + for (String word : dict) { + length = Math.max(length, word.length()); + } + return length; + } +} + + + +/* +Attemp2, Thought: +Use boolena to denote rst[i]: s[0,i-1] can be break to match dict. For the ease to explain, let's consider rst[i+1] with actually string s[0,i]; +How to calculate rst[i+1]? + As long as there is at least 1 way to break s[0, i], that would work. so do a for loop to check on string s[0, i]: + For each i, use another index j, j = 0 ~ i. If rst[j] works and s[j,i+1] is in dict, that makes rst[i+1] = true. + +Correct: however excceeds time limit at 97% correct +*/ + +public class Solution { + public boolean wordBreak(String s, Set dict) { + if (s == null || dict.contains(s)) { + return true; + } + boolean[] rst = new boolean[s.length() + 1]; + rst[0] = true; + for (int i = 0; i < s.length(); i++) { + for (int j = 0; j <= i; j++) { + if (rst[j] && dict.contains(s.substring(j, i + 1))) { + rst[i + 1] = true; + break; + } + } + } + return rst[s.length()]; + } +} + + + + +/* +Thoughts1: +Is this: select one or more words from dict, to construct the given string. +Create DP[i][j] based on dict that says: combine i number of dict strings and j number of dict strings, do we have a combined string that contains the target? + +However, this seems confusing and over-complex. We only have 1 set of variables: dict, so maybe it's now wise to create 2D DP[][]. +*/ \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Word Ladder II.java b/Others/old records/LintCode-Backup/Word Ladder II.java new file mode 100644 index 0000000..8a38c03 --- /dev/null +++ b/Others/old records/LintCode-Backup/Word Ladder II.java @@ -0,0 +1,280 @@ +/* +Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: + +Only one letter can be changed at a time +Each intermediate word must exist in the dictionary +Have you met this question in a real interview? Yes +Example +Given: +start = "hit" +end = "cog" +dict = ["hot","dot","dog","lot","log"] +Return + [ + ["hit","hot","dot","dog","cog"], + ["hit","hot","lot","log","cog"] + ] +Note +All words have the same length. +All words contain only lowercase alphabetic characters. +Tags Expand +Backtracking Depth First Search Breadth First Search + +Attempt1 is by me: however it exceeds time/memory limit. +Some other good sources can be found online: +//http://www.jiuzhang.com/solutions/word-ladder-ii/ +//http://www.cnblogs.com/shawnhue/archive/2013/06/05/leetcode_126.html +Adjacency List, Prefix ... etc. Let's look at them one after another. First get it through with a NineChapter solution +*/ + +//Attempt2: Use Nine Chapter solution, BFS + DFS. It works, very nicely, using backtracking. +/* +BFS: +1. For all mutations in dict, create pastMap: all possible mutations that can turn into each particular str in dict. +2. For all mutations in dict, create distance: distance to start point. +DFS: +3. Find minimum path by checking distance different of just 1. Use a List to do DFS + +Note: +Map uses containsKey. Set uses contains +In DFS, add new copy: new ArrayList(path) +BFS: queue, while loop +DFS: recursion, with a structure to go deeper, remember to add/remove element when passing alone +*/ +public class Solution { + + public List> findLadders(String start, String end, Set dict) { + List> rst = new ArrayList>(); + Map> pastMap = new HashMap>(); + Map distance = new HashMap(); + Queue queue = new LinkedList(); + + //Initiate the variables + dict.add(start); + dict.add(end); + queue.offer(start); + distance.put(start, 0); + for (String s : dict) { + pastMap.put(s, new ArrayList()); + } + + //BFS + BFS(start, end, distance, pastMap, dict, queue); + + //DFS + ArrayList path = new ArrayList(); + DFS(start, end, distance, pastMap, path, rst); + + return rst; + } + //BFS to populate map and distance: + //Distance: distance from each str in dict, to the starting point. + //Map: all possible ways to mutate into each str in dict. + public void BFS(String start, String end, Map distance, Map> pastMap, Set dict, Queue queue) { + while(!queue.isEmpty()) { + String str = queue.poll(); + List list = expand(str, dict); + + for (String s : list) { + pastMap.get(s).add(str); + if (!distance.containsKey(s)) { + distance.put(s, distance.get(str) + 1); + queue.offer(s); + } + } + } + } + //DFS on the map, where map is the all possible ways to mutate into a particular str. Backtracking from end to start + public void DFS(String start, String str, Map distance, Map> pastMap, ArrayList path, List> rst) { + path.add(str); + if (str.equals(start)) { + Collections.reverse(path); + rst.add(new ArrayList(path)); + Collections.reverse(path); + } else {//next step, trace 1 step towards start + for (String s : pastMap.get(str)) {//All previous-mutation options that we have with str: + if (distance.containsKey(s) && distance.get(str) == distance.get(s) + 1) {//Only pick those that's 1 step away: keep minimum steps for optimal solution + DFS(start, s, distance, pastMap, path, rst); + } + } + } + path.remove(path.size() - 1); + } + //Populate all possible mutations for particular str, skipping the case that mutates back to itself. + public ArrayList expand(String str, Set dict) { + ArrayList list = new ArrayList(); + for (int i = 0; i < str.length(); i++) {//Alternate each letter position + for (int j = 0; j < 26; j++) {//Alter 26 letters + if (str.charAt(i) != (char)('a' + j)) { + String newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); + if (dict.contains(newStr)) { + list.add(newStr); + } + } + } + } + return list; + } +} + + + +//Attempt1: probably works, however: +//Testing against input: "qa", "sq", ["si","go","se","cm","so","ph","mt","db","mb","sb","kr","ln","tm","le","av","sm","ar","ci","ca","br","ti","ba","to","ra","fa","yo","ow","sn","ya","cr","po","fe","ho","ma","re","or","rn","au","ur","rh","sr","tc","lt","lo","as","fr","nb","yb","if","pb","ge","th","pm","rb","sh","co","ga","li","ha","hz","no","bi","di","hi","qa","pi","os","uh","wm","an","me","mo","na","la","st","er","sc","ne","mn","mi","am","ex","pt","io","be","fm","ta","tb","ni","mr","pa","he","lr","sq","ye"] +//0. Could be backtrackList exceed memory limit. +//1. If use HashSet set to check if particular sequence exist, then exceed memory +//2. If use StringBuffer strCheck to check if particular sequence exist, then exceed time limit. +//It looks like we'd use DFS for final results. +public class Solution { + private Queue q = new LinkedList(); + private Queue> backtrackList = new LinkedList>(); + private Set dict; + private String end; + private int level = 1; + private int len = Integer.MAX_VALUE; + private List> rst = new ArrayList>(); + + public List> findLadders(String start, String end, Set dict) { + if (start == null || end == null || dict == null || start.length() != end.length()) { + return rst; + } + this.dict = dict; + this.end = end; + ArrayList head = new ArrayList(); + head.add(start); + q.offer(start); + backtrackList.offer(head); + while(!q.isEmpty()) {//BFS + int size = q.size();//Fix size + level++; + for (int k = 0; k < size; k++) {//LOOP through existing queue: for this specific level + String str = q.poll(); + ArrayList list = backtrackList.poll(); + validateMutations(str, list); + }//END FOR K + }//END WHILE + + List> minRst = new ArrayList>(); + for (int i = 0; i < rst.size(); i++) { + if (rst.get(i).size() == len) { + minRst.add(rst.get(i)); + } + } + return minRst; + } + + + public void validateMutations(String str, ArrayList list) { + if (list.size() > len) {//No need to digger further if list is already greater than min length + return; + } + for (int i = 0; i < str.length(); i++) {//Alternate each letter position + for (int j = 0; j < 26; j++) {//Alter 26 letters + if (str.charAt(i) == (char)('a' + j)) { + continue; + } + String newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); + + ArrayList temp = (ArrayList)list.clone(); + temp.add(newStr); + if (dict.contains(newStr)) { + if (newStr.equals(end)) {//Found end + len = Math.min(len, level); + rst.add(temp); + } else { + q.offer(newStr); + backtrackList.offer(temp); + } + } + }//END FOR J + }//END FOR I + } +} + + + +//Solution from NineChapter, commented: + +/* +public class Solution { + public List> findLadders(String start, String end,Set dict) { + List> ladders = new ArrayList>(); + Map> map = new HashMap>(); + Map distance = new HashMap(); + + dict.add(start); + dict.add(end); + + bfs(map, distance, start, end, dict); + //Now at this step, we have: + //a distance map of all mutated string from start, + //a map of mutation and its list of 'pre-mutation' string + //dict: includes start and end + List path = new ArrayList(); + + dfs(ladders, path, end, start, distance, map); + + return ladders; + } + //crt: is not necessarily the 'end', since this is a recursive method + //crt at first is the 'end' string, then it's switching to other strings inorder to finally matches 'start' + void dfs(List> ladders, List path, String crt, + String start, Map distance, + Map> map) { + path.add(crt); + if (crt.equals(start)) {//Now, finally if the crt makes it to start and equals to start, we found a match. + Collections.reverse(path);//We had a reversed path + ladders.add(new ArrayList(path));//add + Collections.reverse(path);//need to reverse it back, becase we need 'path' for more recursive calls. + } else { + for (String next : map.get(crt)) {//Find all possible tranformations/mutations that can turn itself into crt: we have a ArrayList of candidates (pre-mutated strings) + if (distance.containsKey(next) && distance.get(crt) == distance.get(next) + 1) { //if that mutation is just 1 step different, that's good, which means these mutation takes minimum of 1 step to happen. Note: we are comparing the distance to start point. + dfs(ladders, path, next, start, distance, map);//If that's the case, pass varibles to next level: use new path (with crt added), and use the 'next' string (which is 1 step closer to start) for next level of searching. + } + } + } + path.remove(path.size() - 1);//remove that ending crt, since 'path' is shared in recursive methods, need to keep it cleaned. + } +//map: each string in the dict (including start, end) represents a key, and the value is a ArrayList of string. + void bfs(Map> map, Map distance, String start, String end, Set dict) { + Queue q = new LinkedList(); + q.offer(start); + distance.put(start, 0);//Distance: key: str, value: distance value from start. + for (String s : dict) { + map.put(s, new ArrayList()); + } + + while (!q.isEmpty()) { + String crt = q.poll();//Get head of queue, the item currently we are looking at. Called X. + + List nextList = expand(crt, dict);//generate all possible mutations (must exist in dict) + for (String next : nextList) {//For all mutations + map.get(next).add(crt);//append X to end of all of the mutated string (this will become a reverse order). This creates a path of mutation + if (!distance.containsKey(next)) {//If that mutated string never occured: + distance.put(next, distance.get(crt) + 1);//add distance to this mutation. This is fixed and will never change, btw. This becomes a list of all mutations and distance from start. + q.offer(next);//Add this mutation to queue. + } + } + } + } +//all possible mutations based on 1 str polled from the queue. + List expand(String crt, Set dict) { + List expansion = new ArrayList(); + + for (int i = 0; i < crt.length(); i++) { + for (char ch = 'a'; ch <= 'z'; ch++) { + if (ch != crt.charAt(i)) { + String expanded = crt.substring(0, i) + ch + + crt.substring(i + 1); + if (dict.contains(expanded)) { + expansion.add(expanded); + } + } + } + } + return expansion; + } +} + + +*/ \ No newline at end of file diff --git a/Others/old records/LintCode-Backup/Word Ladder.java b/Others/old records/LintCode-Backup/Word Ladder.java new file mode 100644 index 0000000..d15adbf --- /dev/null +++ b/Others/old records/LintCode-Backup/Word Ladder.java @@ -0,0 +1,126 @@ +/* +Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that: + +Only one letter can be changed at a time +Each intermediate word must exist in the dictionary + +Example +Given: +start = "hit" +end = "cog" +dict = ["hot","dot","dog","lot","log"] +As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", +return its length 5. + +Note +Return 0 if there is no such transformation sequence. +All words have the same length. +All words contain only lowercase alphabetic characters. +Tags Expand +Breadth First Search + +Thoughts: +Use the dict (check if mutation exist in dict) as base to create a directed graph, use BFS to find shortest path. + +Note: +Be careful with queue size when trying to do for loop on it. Use a pre-fixed size = q.size(), in case queue's size changes during for loop. +*/ + +//Solution1: nested for loop +public class Solution { + public int ladderLength(String start, String end, Set dict) { + if (start == null || end == null || dict == null || start.length() != end.length()) { + return 0; + } + Queue q = new LinkedList(); + HashSet set = new HashSet(); + int level = 1; + int len = Integer.MAX_VALUE; + q.offer(start); + set.add(start); + while(!q.isEmpty()) {//BFS + int size = q.size();//Fix size + level++; + for (int k = 0; k < size; k++) {//LOOP through existing queue: for this specific level + String str = q.poll(); + for (int i = 0; i < str.length(); i++) {//Alternate each letter position + for (int j = 0; j < 26; j++) {//Alter 26 letters + String newStr; + if (i == 0 && str.length() == 1) { + newStr = "" + (char)('a' + j); + } + else if (i == str.length() - 1) { + newStr = str.substring(0, i) + (char)('a' + j); + } else { + newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); + } + if (!set.contains(newStr) && dict.contains(newStr)) { + if (newStr.equals(end)) {//Found end + len = Math.min(len, level); + } else { + set.add(newStr); + q.offer(newStr); + } + } + }//END FOR J + }//END FOR I + }//END FOR K + }//END WHILE + return len; + } +} + + + +//Solution2: separate methods, and hope to make Word Ladder II problem easier +public class Solution { + private Queue q = new LinkedList(); + private HashSet set = new HashSet(); + private Set dict; + private String end; + private int level = 1; + private int len = Integer.MAX_VALUE; + + public int ladderLength(String start, String end, Set dict) { + if (start == null || end == null || dict == null || start.length() != end.length()) { + return 0; + } + this.dict = dict; + this.end = end; + q.offer(start); + set.add(start); + while(!q.isEmpty()) {//BFS + int size = q.size();//Fix size + level++; + for (int k = 0; k < size; k++) {//LOOP through existing queue: for this specific level + String str = q.poll(); + validateMutations(str); + }//END FOR K + }//END WHILE + return len; + } + + public void validateMutations(String str) { + for (int i = 0; i < str.length(); i++) {//Alternate each letter position + for (int j = 0; j < 26; j++) {//Alter 26 letters + String newStr; + if (i == 0 && str.length() == 1) { + newStr = "" + (char)('a' + j); + } + else if (i == str.length() - 1) { + newStr = str.substring(0, i) + (char)('a' + j); + } else { + newStr = str.substring(0, i) + (char)('a' + j) + str.substring(i + 1); + } + if (!set.contains(newStr) && dict.contains(newStr)) { + if (newStr.equals(end)) {//Found end + len = Math.min(len, level); + } else { + set.add(newStr); + q.offer(newStr); + } + } + }//END FOR J + }//END FOR I + } +} diff --git a/Others/old records/LintCode-Backup/Word Search II.java b/Others/old records/LintCode-Backup/Word Search II.java new file mode 100644 index 0000000..30f77a3 --- /dev/null +++ b/Others/old records/LintCode-Backup/Word Search II.java @@ -0,0 +1,210 @@ +/* +Given a matrix of lower alphabets and a dictionary. Find all words in the dictionary that can be found in the matrix. A word can start from any position in the matrix and go left/right/up/down to the adjacent position. + +Example +Given matrix: +doaf +agai +dcan +and dictionary: +{"dog", "dad", "dgdg", "can", "again"} + +return {"dog", "dad", "can", "again"} + + +dog: +doaf +agai +dcan + +dad: +doaf +agai +dcan + +can: +doaf +agai +dcan + +again: +doaf +agai +dcan + +Challenge +Using trie to implement your algorithm. + +Tags Expand +LintCode Copyright Trie + + +*/ +//Well, the attempt2 uses Trie, but didn't really use find(). It just uses insert() to create Trie, and mainly +//used the end point where string is finished. + +/* +Attemp2: Trie solution. +http://www.jiuzhang.com/solutions/word-search-ii/ + +Here is how Tire works, from my understanding: it creates a new data strucutre that maps all words into a trie structure. Then, based on the given 2D matrix of letters, using each individual letter as starting point, and grab all possible combinations, then save the possibilities into final resuts. + +The magic 'checking point' is the use of 'isString' of trie. + +Note: should also be careful with marking board[x][y] = '#', which helps to prevent re-use used letters. + +About TrieTree: +Each string obtains a particular/unique path. +Different strings could share same prefix path, but at certain index when the two strings are differentiating, they will start the following path on different TrieNode, which leads to completely separate subtree path. +At end of the tree, a string will have isString== true and the real string value stored. + +That is, +insert: for all letter, make sure they are all created as nodes and linked together by using subtree. +find: for loop to iterate through subtrees of nodes, then return target on last index letter. + + +In the search: +node.subtree.get(current).isString: this determines if a string exists or not. +*/ +public class Solution { + class TrieNode { + boolean isString; + String s; + HashMap subtree; + public TrieNode() { + this.isString = false; + this.s = ""; + this.subtree = new HashMap(); + } + } + + class TrieTree { + TrieNode node; + public TrieTree(TrieNode n) { + node = n; + } + public void insert(String s) { + TrieNode curr = node; + for (int i = 0; i < s.length(); i++) { + if (!curr.subtree.containsKey(s.charAt(i))) { + curr.subtree.put(s.charAt(i), new TrieNode()); + } + curr = curr.subtree.get(s.charAt(i)); + } + curr.isString = true; + curr.s = s; + } + public boolean find(String s) { + TrieNode curr = node; + for (int i = 0; i < s.length(); i++) { + if (!curr.subtree.containsKey(s.charAt(i))) { + return false; + } + curr = curr.subtree.get(s.charAt(i)); + } + return curr.isString; + } + } + + public void search(char[][] board, ArrayList rst, int i, int j, TrieNode node) { + if (node.isString) { + if(!rst.contains(node.s)) { + rst.add(node.s); + } + } + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] == '#' || node == null) { + return; + } + if (node.subtree.containsKey(board[i][j])) { + char temp = board[i][j]; + TrieNode next = node.subtree.get(board[i][j]); + board[i][j] = '#';//Mark it, prevent going back-forth + search(board, rst, i, j + 1, next); + search(board, rst, i, j - 1, next); + search(board, rst, i - 1, j, next); + search(board, rst, i + 1, j, next); + board[i][j] = temp; + } + + } + public ArrayList wordSearchII(char[][] board, ArrayList words) { + ArrayList rst = new ArrayList(); + if (board == null || words == null || words.size() == 0) { + return rst; + } + TrieTree tree = new TrieTree(new TrieNode()); + for (String word : words) { + tree.insert(word); + } + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[i].length; j++) { + search(board, rst, i, j, tree.node); + } + } + + return rst; + } +} + + + + + +/* +Attempt1: +Thoughts: +Use word search1, and do for loop on the words... and that works .........Well, that's not the Trie solution +*/ + +public class Solution { + public ArrayList wordSearchII(char[][] board, ArrayList words) { + ArrayList rst = new ArrayList(); + if (board == null || words == null || words.size() == 0) { + return rst; + } + for (String word : words) { + if (exist(board, word)) { + rst.add(word); + } + } + return rst; + } + //The following are from Word Search I + public boolean exist(char[][] board, String word) { + if (word == null || word.length() == 0) { + return true; + } + if (board == null) { + return false; + } + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + if (board[i][j] == word.charAt(0)) { + boolean rst = search(board, word, i, j, 0); + if (rst) { + return true; + } + } + } + } + return false; + } + + public boolean search(char[][] board, String word, int i, int j, int start) { + if (start == word.length()) { + return true; + } + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { + return false; + } + board[i][j] = '#'; + boolean rst = search(board, word, i, j - 1, start + 1) + || search(board, word, i, j + 1, start + 1) + || search(board, word, i + 1, j, start + 1) + || search(board, word, i - 1, j, start + 1); + board[i][j] = word.charAt(start); + return rst; + } +} diff --git a/Others/old records/LintCode-Backup/Word Search.java b/Others/old records/LintCode-Backup/Word Search.java new file mode 100644 index 0000000..013dbb9 --- /dev/null +++ b/Others/old records/LintCode-Backup/Word Search.java @@ -0,0 +1,70 @@ +/* +Given a 2D board and a word, find if the word exists in the grid. + +The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. + +Have you met this question in a real interview? Yes +Example +Given board = + +[ + "ABCE", + "SFCS", + "ADEE" +] +word = "ABCCED", -> returns true, +word = "SEE", -> returns true, +word = "ABCB", -> returns false. + +Tags Expand +Backtracking + +Thoughts: +1. find starting index i,j +2. Start divde&&conqure: each iteration. + In each interation: make sure board[i][j] == word.charAt(currentCheckingIndex); If not match, return false and terminate the interation +3. Therefore, if (start) == word.length(), that means all previous-start indexes are matched, so we have a match; return true in this case. + + +Note: if can use boolean || boolean || boolean, use it and save processing power: once one boolean works, it won't process the rest || elements +*/ + + +public class Solution { + public boolean exist(char[][] board, String word) { + if (word == null || word.length() == 0) { + return true; + } + if (board == null) { + return false; + } + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + if (board[i][j] == word.charAt(0)) { + boolean rst = search(board, word, i, j, 0); + if (rst) { + return true; + } + } + } + } + return false; + } + + public boolean search(char[][] board, String word, int i, int j, int start) { + if (start == word.length()) { + return true; + } + if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(start)) { + return false; + } + board[i][j] = '#'; + boolean rst = search(board, word, i, j - 1, start + 1) + || search(board, word, i, j + 1, start + 1) + || search(board, word, i + 1, j, start + 1) + || search(board, word, i - 1, j, start + 1); + board[i][j] = word.charAt(start); + return rst; + } +} diff --git "a/Others/\344\272\232\351\272\273/FindFirstDuplicate.java" "b/Others/\344\272\232\351\272\273/FindFirstDuplicate.java" new file mode 100644 index 0000000..aa51f87 --- /dev/null +++ "b/Others/\344\272\232\351\272\273/FindFirstDuplicate.java" @@ -0,0 +1,37 @@ +/* + 给你一个字符串,找出其中第一个重复的单词。比如,He had had a book. 返回had。 + 若真是这么简单, loop through str by ' '。每个单词都尝试在str里面找重复 + + regular expression: "\\s+" +*/ + +public class Solution { + + public static String findFirstDuplicatedWord(String str) { + if (str == null || str.length() == 0) { + return str; + } + + String[] arr = str.split("\\s+"); + ArrayList list = new ArrayList(); + for (int i = 0; i < arr.length; i++) { + if (list.contains(arr[i])) { + return arr[i]; + } + list.add(arr[i]); + } + + return ""; + } + + public static void main(String[] args) { + System.out.println("START"); + + String str = "a is a sample program ok a";// is a a is + + String rst = findFirstDuplicatedWord(str); + + System.out.println(rst); + } + +} \ No newline at end of file diff --git "a/Others/\344\272\232\351\272\273/Slot Machine.java" "b/Others/\344\272\232\351\272\273/Slot Machine.java" new file mode 100644 index 0000000..1a255a2 --- /dev/null +++ "b/Others/\344\272\232\351\272\273/Slot Machine.java" @@ -0,0 +1,102 @@ +M + +检查字符串是否可以组成回文. 用hashmap + +``` +import java.io.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.util.regex.*; + +/* +Summer has reached a casino in Las Vegas and she wanted to gamble in the slot machines, Casino manager has given her some chances to play (T) ,where T is the no of different slot machines; each one has it's own unique combination of letters and numbers blinking in the panel(N). + +The condition of winning is to have a pallindromic sequence within those N characters provided she can press the randomization switch as many times she wants untill all the combinations with those letters are complete. + +Help summer to identify in which of those slot machines she has a chance of winning. + +Constraints: + +1≤T≤10000 + +1≤N≤100 (characters) + +Input Format + +The first line contains an integer T (The no of slot machines). + +The second line contains the string of characters(N) blinking on the slot machine. + +The string inputed in the second line may cotain any numbers or letters of any length . + +Note : + +The string(N) may have repetitive letters or numbers in it. Capital letters and small letters are considered separate characters. + +Output Format + +if a slot machine has a possibility of winning then display yes, else display no + +Sample Input + +2 + +abac11c + +dkvvfvd + +Sample Output + +yes + +no + +Explanation + +Since the 1st string contains a permutation which is palindromic in nature 'ca1b1ac' therefore output is yes. + +In the 2nd case there is no such permutation hence the output is no. + +*/ +//check pallidromic by counting chars in HashMap. O(n). If more than 1 single char, that is no. +public class Solution { + + public static void main(String[] args) { + /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */ + Scanner in = new Scanner(System.in); + int line = Integer.parseInt(in.nextLine()); + while (in.hasNextLine()) { + if (checkPalindrome(in.nextLine())) { + System.out.println("Yes"); + } else { + System.out.println("No"); + } + } + } + + public static boolean checkPalindrome(String s) { + if (s == null || s.length() == 0) { + return false; + } + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (!map.containsKey(c)) { + map.put(c, 0); + } + map.put(c, map.get(c) + 1); + } + int countSingle = 0; + for (Map.Entry entry : map.entrySet()) { + countSingle += entry.getValue() % 2; + if (countSingle > 1) { + return false; + } + } + return true; + } + + +} +``` \ No newline at end of file diff --git a/README.md b/README.md index 85fdb2e..77dec2a 100644 --- a/README.md +++ b/README.md @@ -1,252 +1,335 @@ -# LintCode +# Java Algorithm Problems -To host Java Solutions to problems from LintCode(http://LintCode.com). +### 前戏 +To host Java Solutions to algorithm problems from LintCode, LeetCode...etc. I Will try to revise the solutions once new problem or new testing case occurs. +**Mid 2016** I realize that people may want to contribute to this repo, and make it better by contributing fixes, better solutions ... etc. Free free to send pull request. Once verified, I'm happy to merge in! +CALM DOWN AND CODE ON! Fellows! -| Squence | Problem | Level | Language | -|:-------:|:--------------|:---------------|:---------:| -|0|[2 Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/2 Sum.java)| |Java| -|1|[3 Sum Closest.java](https://github.com/shawnfan/LintCode/blob/master/Java/3 Sum Closest.java)| |Java| -|2|[3 Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/3 Sum.java)| |Java| -|3|[4 Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/4 Sum.java)| |Java| -|4|[A+B.java](https://github.com/shawnfan/LintCode/blob/master/Java/A+B.java)| |Java| -|5|[Add and Search Word.java](https://github.com/shawnfan/LintCode/blob/master/Java/Add and Search Word.java)| |Java| -|6|[Add Binary.java](https://github.com/shawnfan/LintCode/blob/master/Java/Add Binary.java)| |Java| -|7|[Add Two Numbers II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Add Two Numbers II.java)| |Java| -|8|[Anagrams.java](https://github.com/shawnfan/LintCode/blob/master/Java/Anagrams.java)| |Java| -|9|[Backpack II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Backpack II.java)| |Java| -|10|[Backpack.java](https://github.com/shawnfan/LintCode/blob/master/Java/Backpack.java)| |Java| -|11|[Balanced Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Balanced Binary Tree.java)| |Java| -|12|[Best Time to Buy and Sell Stock I.java](https://github.com/shawnfan/LintCode/blob/master/Java/Best Time to Buy and Sell Stock I.java)| |Java| -|13|[Best Time to Buy and Sell Stock II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Best Time to Buy and Sell Stock II.java)| |Java| -|14|[Best Time to Buy and Sell Stock III .java](https://github.com/shawnfan/LintCode/blob/master/Java/Best Time to Buy and Sell Stock III .java)| |Java| -|15|[Best Time to Buy and Sell Stock IV.java](https://github.com/shawnfan/LintCode/blob/master/Java/Best Time to Buy and Sell Stock IV.java)| |Java| -|16|[Binary Representation.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Representation.java)| |Java| -|17|[Binary Search Tree Iterator.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Search Tree Iterator.java)| |Java| -|18|[Binary Search.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Search.java)| |Java| -|19|[Binary Tree Inorder Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Inorder Traversal.java)| |Java| -|20|[Binary Tree Level Order Traversal II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Level Order Traversal II.java)| |Java| -|21|[Binary Tree Level Order Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Level Order Traversal.java)| |Java| -|22|[Binary Tree Maximum Path Sum II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Maximum Path Sum II.java)| |Java| -|23|[Binary Tree Maximum Path Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Maximum Path Sum.java)| |Java| -|24|[Binary Tree Path Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Path Sum.java)| |Java| -|25|[Binary Tree Paths.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Paths.java)| |Java| -|26|[Binary Tree Postorder Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Postorder Traversal.java)| |Java| -|27|[Binary Tree Preorder Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Preorder Traversal.java)| |Java| -|28|[Binary Tree Zigzag Level Order Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Binary Tree Zigzag Level Order Traversal.java)| |Java| -|29|[Building Outline.java](https://github.com/shawnfan/LintCode/blob/master/Java/Building Outline.java)| |Java| -|30|[Classical Binary Search.java](https://github.com/shawnfan/LintCode/blob/master/Java/Classical Binary Search.java)| |Java| -|31|[Climbing Stairs.java](https://github.com/shawnfan/LintCode/blob/master/Java/Climbing Stairs.java)| |Java| -|32|[Clone Graph.java](https://github.com/shawnfan/LintCode/blob/master/Java/Clone Graph.java)| |Java| -|33|[Closest Number in Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Closest Number in Sorted Array.java)| |Java| -|34|[Coins in a Line.java](https://github.com/shawnfan/LintCode/blob/master/Java/Coins in a Line.java)| |Java| -|35|[Combination Sum II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Combination Sum II.java)| |Java| -|36|[Combination Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Combination Sum.java)| |Java| -|37|[Combinations.java](https://github.com/shawnfan/LintCode/blob/master/Java/Combinations.java)| |Java| -|38|[Compare Strings.java](https://github.com/shawnfan/LintCode/blob/master/Java/Compare Strings.java)| |Java| -|39|[Complete Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Complete Binary Tree.java)| |Java| -|40|[Construct Binary Tree from Inorder and Postorder Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Construct Binary Tree from Inorder and Postorder Traversal.java)| |Java| -|41|[Construct Binary Tree from Inorder and Preorder Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Construct Binary Tree from Inorder and Preorder Traversal.java)| |Java| -|42|[Container With Most Water.java](https://github.com/shawnfan/LintCode/blob/master/Java/Container With Most Water.java)| |Java| -|43|[Convert Binary Search Tree to Doubly Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Binary Search Tree to Doubly Linked List.java)| |Java| -|44|[Convert Expression to Polish Notation.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Expression to Polish Notation.java)| |Java| -|45|[Convert Expression to Reverse Polish Notation.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Expression to Reverse Polish Notation.java)| |Java| -|46|[Convert Integer A to Integer B.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Integer A to Integer B.java)| |Java| -|47|[Convert Sorted Array to Binary Search Tree With Minimal Height.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Sorted Array to Binary Search Tree With Minimal Height.java)| |Java| -|48|[Convert Sorted List to Binary Search Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Convert Sorted List to Binary Search Tree.java)| |Java| -|49|[Copy List with Random Pointer.java](https://github.com/shawnfan/LintCode/blob/master/Java/Copy List with Random Pointer.java)| |Java| -|50|[Cosine Similarity.java](https://github.com/shawnfan/LintCode/blob/master/Java/Cosine Similarity.java)| |Java| -|51|[Count 1 in Binary.java](https://github.com/shawnfan/LintCode/blob/master/Java/Count 1 in Binary.java)| |Java| -|52|[Count and Say.java](https://github.com/shawnfan/LintCode/blob/master/Java/Count and Say.java)| |Java| -|53|[Count of Smaller Number before itself.java](https://github.com/shawnfan/LintCode/blob/master/Java/Count of Smaller Number before itself.java)| |Java| -|54|[Count of Smaller Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Count of Smaller Number.java)| |Java| -|55|[Data Stream Median.java](https://github.com/shawnfan/LintCode/blob/master/Java/Data Stream Median.java)| |Java| -|56|[Delete Digits.java](https://github.com/shawnfan/LintCode/blob/master/Java/Delete Digits.java)| |Java| -|57|[Delete Node in the Middle of Singly Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Delete Node in the Middle of Singly Linked List.java)| |Java| -|58|[Distinct Subsequences.java](https://github.com/shawnfan/LintCode/blob/master/Java/Distinct Subsequences.java)| |Java| -|59|[Easy Reverse Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Easy Reverse Linked List.java)| |Java| -|60|[Edit Distance.java](https://github.com/shawnfan/LintCode/blob/master/Java/Edit Distance.java)| |Java| -|61|[Expression Evaluation.java](https://github.com/shawnfan/LintCode/blob/master/Java/Expression Evaluation.java)| |Java| -|62|[Expression Tree Build.java](https://github.com/shawnfan/LintCode/blob/master/Java/Expression Tree Build.java)| |Java| -|63|[Fast Power.java](https://github.com/shawnfan/LintCode/blob/master/Java/Fast Power.java)| |Java| -|64|[Fibonacci.java](https://github.com/shawnfan/LintCode/blob/master/Java/Fibonacci.java)| |Java| -|65|[Find Minimum in Rotated Sorted Array II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find Minimum in Rotated Sorted Array II.java)| |Java| -|66|[Find Minimum in Rotated Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find Minimum in Rotated Sorted Array.java)| |Java| -|67|[Find Peak Element II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find Peak Element II.java)| |Java| -|68|[Find Peak Element.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find Peak Element.java)| |Java| -|69|[Find the Connected Component in the Undirected Graph.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find the Connected Component in the Undirected Graph.java)| |Java| -|70|[Find the Weak Connected Component in the Directed Graph.java](https://github.com/shawnfan/LintCode/blob/master/Java/Find the Weak Connected Component in the Directed Graph.java)| |Java| -|71|[First Bad Version.java](https://github.com/shawnfan/LintCode/blob/master/Java/First Bad Version.java)| |Java| -|72|[First Missing Positive.java](https://github.com/shawnfan/LintCode/blob/master/Java/First Missing Positive.java)| |Java| -|73|[Flatten Binary Tree to Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Flatten Binary Tree to Linked List.java)| |Java| -|74|[Gas Station.java](https://github.com/shawnfan/LintCode/blob/master/Java/Gas Station.java)| |Java| -|75|[Generate Parentheses.java](https://github.com/shawnfan/LintCode/blob/master/Java/Generate Parentheses.java)| |Java| -|76|[Graph Valid Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Graph Valid Tree.java)| |Java| -|77|[Hash Function.java](https://github.com/shawnfan/LintCode/blob/master/Java/Hash Function.java)| |Java| -|78|[HashWithArray.java](https://github.com/shawnfan/LintCode/blob/master/Java/HashWithArray.java)| |Java| -|79|[Heapify.java](https://github.com/shawnfan/LintCode/blob/master/Java/Heapify.java)| |Java| -|80|[House Robber.java](https://github.com/shawnfan/LintCode/blob/master/Java/House Robber.java)| |Java| -|81|[Identical Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Identical Binary Tree.java)| |Java| -|82|[Implement Queue by Two Stacks.java](https://github.com/shawnfan/LintCode/blob/master/Java/Implement Queue by Two Stacks.java)| |Java| -|83|[Implement Trie.java](https://github.com/shawnfan/LintCode/blob/master/Java/Implement Trie.java)| |Java| -|84|[Insert Interval.java](https://github.com/shawnfan/LintCode/blob/master/Java/Insert Interval.java)| |Java| -|85|[Insert Node in a Binary Search Tree .java](https://github.com/shawnfan/LintCode/blob/master/Java/Insert Node in a Binary Search Tree .java)| |Java| -|86|[Insertion Sort List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Insertion Sort List.java)| |Java| -|87|[Interleaving Positive and Negative Numbers.java](https://github.com/shawnfan/LintCode/blob/master/Java/Interleaving Positive and Negative Numbers.java)| |Java| -|88|[Interleaving String.java](https://github.com/shawnfan/LintCode/blob/master/Java/Interleaving String.java)| |Java| -|89|[Intersection of Two Linked Lists.java](https://github.com/shawnfan/LintCode/blob/master/Java/Intersection of Two Linked Lists.java)| |Java| -|90|[Interval Minimum Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Interval Minimum Number.java)| |Java| -|91|[Interval Sum II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Interval Sum II.java)| |Java| -|92|[Interval Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Interval Sum.java)| |Java| -|93|[Invert Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Invert Binary Tree.java)| |Java| -|94|[Jump Game II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Jump Game II.java)| |Java| -|95|[Jump Game.java](https://github.com/shawnfan/LintCode/blob/master/Java/Jump Game.java)| |Java| -|96|[Kth Largest Element.java](https://github.com/shawnfan/LintCode/blob/master/Java/Kth Largest Element.java)| |Java| -|97|[Kth Smallest Sum In Two Sorted Arrays.java](https://github.com/shawnfan/LintCode/blob/master/Java/Kth Smallest Sum In Two Sorted Arrays.java)| |Java| -|98|[Largest Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Largest Number.java)| |Java| -|99|[Largest Rectangle in Histogram.java](https://github.com/shawnfan/LintCode/blob/master/Java/Largest Rectangle in Histogram.java)| |Java| -|100|[Last Position of Target.java](https://github.com/shawnfan/LintCode/blob/master/Java/Last Position of Target.java)| |Java| -|101|[Length of Last Word.java](https://github.com/shawnfan/LintCode/blob/master/Java/Length of Last Word.java)| |Java| -|102|[Letter Combinations of a Phone Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Letter Combinations of a Phone Number.java)| |Java| -|103|[Linked List Cycle II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Linked List Cycle II.java)| |Java| -|104|[Linked List Cycle.java](https://github.com/shawnfan/LintCode/blob/master/Java/Linked List Cycle.java)| |Java| -|105|[Longest Common Prefix.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Common Prefix.java)| |Java| -|106|[Longest Common Subsequence.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Common Subsequence.java)| |Java| -|107|[Longest Common Substring.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Common Substring.java)| |Java| -|108|[Longest Consecutive Sequence.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Consecutive Sequence.java)| |Java| -|109|[Longest Increasing Continuous subsequence II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Increasing Continuous subsequence II.java)| |Java| -|110|[Longest Increasing Continuous subsequence.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Increasing Continuous subsequence.java)| |Java| -|111|[Longest Increasing Subsequence.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Increasing Subsequence.java)| |Java| -|112|[Longest Palindromic Substring.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Palindromic Substring.java)| |Java| -|113|[Longest Substring with At Most K Distinct Characters.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Substring with At Most K Distinct Characters.java)| |Java| -|114|[Longest Substring Without Repeating Characters.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Substring Without Repeating Characters.java)| |Java| -|115|[Longest Words.java](https://github.com/shawnfan/LintCode/blob/master/Java/Longest Words.java)| |Java| -|116|[Lowest Common Ancestor II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Lowest Common Ancestor II.java)| |Java| -|117|[Lowest Common Ancestor.java](https://github.com/shawnfan/LintCode/blob/master/Java/Lowest Common Ancestor.java)| |Java| -|118|[Majority Number II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Majority Number II.java)| |Java| -|119|[Majority Number III.java](https://github.com/shawnfan/LintCode/blob/master/Java/Majority Number III.java)| |Java| -|120|[Majority Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Majority Number.java)| |Java| -|121|[Matrix Zigzag Traversal.java](https://github.com/shawnfan/LintCode/blob/master/Java/Matrix Zigzag Traversal.java)| |Java| -|122|[Max Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Max Tree.java)| |Java| -|123|[Maximal Square.java](https://github.com/shawnfan/LintCode/blob/master/Java/Maximal Square.java)| |Java| -|124|[Maximum Depth of Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Maximum Depth of Binary Tree.java)| |Java| -|125|[Maximum Product Subarray.java](https://github.com/shawnfan/LintCode/blob/master/Java/Maximum Product Subarray.java)| |Java| -|126|[Maximum Subarray III.java](https://github.com/shawnfan/LintCode/blob/master/Java/Maximum Subarray III.java)| |Java| -|127|[MaximumSubarray.java](https://github.com/shawnfan/LintCode/blob/master/Java/MaximumSubarray.java)| |Java| -|128|[MaximumSubarrayII.java](https://github.com/shawnfan/LintCode/blob/master/Java/MaximumSubarrayII.java)| |Java| -|129|[Median of two Sorted Arrays.java](https://github.com/shawnfan/LintCode/blob/master/Java/Median of two Sorted Arrays.java)| |Java| -|130|[Median.java](https://github.com/shawnfan/LintCode/blob/master/Java/Median.java)| |Java| -|131|[Merge Intervals.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge Intervals.java)| |Java| -|132|[Merge k Sorted Arrays.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge k Sorted Arrays.java)| |Java| -|133|[Merge k Sorted Lists.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge k Sorted Lists.java)| |Java| -|134|[Merge Sorted Array II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge Sorted Array II.java)| |Java| -|135|[Merge Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge Sorted Array.java)| |Java| -|136|[Merge Two Sorted List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Merge Two Sorted List.java)| |Java| -|137|[Middle of Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Middle of Linked List.java)| |Java| -|138|[Min Stack.java](https://github.com/shawnfan/LintCode/blob/master/Java/Min Stack.java)| |Java| -|139|[Minimum Path Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Minimum Path Sum.java)| |Java| -|140|[Minimum Size Subarray Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Minimum Size Subarray Sum.java)| |Java| -|141|[Minimum Subarray.java](https://github.com/shawnfan/LintCode/blob/master/Java/Minimum Subarray.java)| |Java| -|142|[Minimum Window Substring.java](https://github.com/shawnfan/LintCode/blob/master/Java/Minimum Window Substring.java)| |Java| -|143|[MinimumDepthOfBinaryTree.java](https://github.com/shawnfan/LintCode/blob/master/Java/MinimumDepthOfBinaryTree.java)| |Java| -|144|[Next Permutation.java](https://github.com/shawnfan/LintCode/blob/master/Java/Next Permutation.java)| |Java| -|145|[NQueens.java](https://github.com/shawnfan/LintCode/blob/master/Java/NQueens.java)| |Java| -|146|[NQueensII.java](https://github.com/shawnfan/LintCode/blob/master/Java/NQueensII.java)| |Java| -|147|[Nth to Last Node in List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Nth to Last Node in List.java)| |Java| -|148|[Number of Airplane in the sky.java](https://github.com/shawnfan/LintCode/blob/master/Java/Number of Airplane in the sky.java)| |Java| -|149|[Number of Islands II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Number of Islands II.java)| |Java| -|150|[Number of Islands.java](https://github.com/shawnfan/LintCode/blob/master/Java/Number of Islands.java)| |Java| -|151|[Number Triangles.java](https://github.com/shawnfan/LintCode/blob/master/Java/Number Triangles.java)| |Java| -|152|[O(1) Check Power of 2.java](https://github.com/shawnfan/LintCode/blob/master/Java/O(1) Check Power of 2.java)| |Java| -|153|[Palindrome Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Palindrome Linked List.java)| |Java| -|154|[Palindrome Partitioning II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Palindrome Partitioning II.java)| |Java| -|155|[Palindrome Partitioning.java](https://github.com/shawnfan/LintCode/blob/master/Java/Palindrome Partitioning.java)| |Java| -|156|[Partition Array by Odd and Even.java](https://github.com/shawnfan/LintCode/blob/master/Java/Partition Array by Odd and Even.java)| |Java| -|157|[Partition Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Partition Array.java)| |Java| -|158|[Partition List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Partition List.java)| |Java| -|159|[Permutation Index.java](https://github.com/shawnfan/LintCode/blob/master/Java/Permutation Index.java)| |Java| -|160|[Permutations II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Permutations II.java)| |Java| -|161|[Permutations.java](https://github.com/shawnfan/LintCode/blob/master/Java/Permutations.java)| |Java| -|162|[Plus One.java](https://github.com/shawnfan/LintCode/blob/master/Java/Plus One.java)| |Java| -|163|[Pow(x,n).java](https://github.com/shawnfan/LintCode/blob/master/Java/Pow(x,n).java)| |Java| -|164|[Product of Array Exclude Itself.java](https://github.com/shawnfan/LintCode/blob/master/Java/Product of Array Exclude Itself.java)| |Java| -|165|[QuickSort.java](https://github.com/shawnfan/LintCode/blob/master/Java/QuickSort.java)| |Java| -|166|[Recover Rotated Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Recover Rotated Sorted Array.java)| |Java| -|167|[Rehashing.java](https://github.com/shawnfan/LintCode/blob/master/Java/Rehashing.java)| |Java| -|168|[Remove Duplicates from Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Duplicates from Sorted Array.java)| |Java| -|169|[Remove Duplicates from Sorted List II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Duplicates from Sorted List II.java)| |Java| -|170|[Remove Duplicates from Sorted List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Duplicates from Sorted List.java)| |Java| -|171|[Remove Duplicates from Unsorted List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Duplicates from Unsorted List.java)| |Java| -|172|[Remove Linked List Elements.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Linked List Elements.java)| |Java| -|173|[Remove Node in Binary Search Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Node in Binary Search Tree.java)| |Java| -|174|[Remove Nth Node From End of List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Remove Nth Node From End of List.java)| |Java| -|175|[Reorder List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Reorder List.java)| |Java| -|176|[Reverse Integer.java](https://github.com/shawnfan/LintCode/blob/master/Java/Reverse Integer.java)| |Java| -|177|[Reverse Linked List II .java](https://github.com/shawnfan/LintCode/blob/master/Java/Reverse Linked List II .java)| |Java| -|178|[Reverse Linked List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Reverse Linked List.java)| |Java| -|179|[Reverse Words in a String.java](https://github.com/shawnfan/LintCode/blob/master/Java/Reverse Words in a String.java)| |Java| -|180|[Rotate List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Rotate List.java)| |Java| -|181|[Rotate String.java](https://github.com/shawnfan/LintCode/blob/master/Java/Rotate String.java)| |Java| -|182|[Search a 2D Matrix II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search a 2D Matrix II.java)| |Java| -|183|[Search a 2D Matrix.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search a 2D Matrix.java)| |Java| -|184|[Search for a Range.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search for a Range.java)| |Java| -|185|[Search Insert Position.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search Insert Position.java)| |Java| -|186|[Search Range in Binary Search Tree .java](https://github.com/shawnfan/LintCode/blob/master/Java/Search Range in Binary Search Tree .java)| |Java| -|187|[Search Rotated in Sorted Array II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search Rotated in Sorted Array II.java)| |Java| -|188|[Search Rotated in Sorted Array.java](https://github.com/shawnfan/LintCode/blob/master/Java/Search Rotated in Sorted Array.java)| |Java| -|189|[Segment Tree Build II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Segment Tree Build II.java)| |Java| -|190|[Segment Tree Build.java](https://github.com/shawnfan/LintCode/blob/master/Java/Segment Tree Build.java)| |Java| -|191|[Segment Tree Modify.java](https://github.com/shawnfan/LintCode/blob/master/Java/Segment Tree Modify.java)| |Java| -|192|[Segment Tree Query II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Segment Tree Query II.java)| |Java| -|193|[Segment Tree Query.java](https://github.com/shawnfan/LintCode/blob/master/Java/Segment Tree Query.java)| |Java| -|194|[Serilization and Deserialization Of Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Serilization and Deserialization Of Binary Tree.java)| |Java| -|195|[Single Number II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Single Number II.java)| |Java| -|196|[Single Number III.java](https://github.com/shawnfan/LintCode/blob/master/Java/Single Number III.java)| |Java| -|197|[Single Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Single Number.java)| |Java| -|198|[Singleton.java](https://github.com/shawnfan/LintCode/blob/master/Java/Singleton.java)| |Java| -|199|[Sliding Window Maximum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sliding Window Maximum.java)| |Java| -|200|[Sliding Window Median.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sliding Window Median.java)| |Java| -|201|[Sort Color.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sort Color.java)| |Java| -|202|[Sort Colors II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sort Colors II.java)| |Java| -|203|[Sort Letters by Case.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sort Letters by Case.java)| |Java| -|204|[Sort List.java](https://github.com/shawnfan/LintCode/blob/master/Java/Sort List.java)| |Java| -|205|[Space Replacement.java](https://github.com/shawnfan/LintCode/blob/master/Java/Space Replacement.java)| |Java| -|206|[Sqrt(x).java](https://github.com/shawnfan/LintCode/blob/master/Java/Sqrt(x).java)| |Java| -|207|[Stone Game.java](https://github.com/shawnfan/LintCode/blob/master/Java/Stone Game.java)| |Java| -|208|[String to Integer(atoi).java](https://github.com/shawnfan/LintCode/blob/master/Java/String to Integer(atoi).java)| |Java| -|209|[StrStr.java](https://github.com/shawnfan/LintCode/blob/master/Java/StrStr.java)| |Java| -|210|[Subarray Sum Closest.java](https://github.com/shawnfan/LintCode/blob/master/Java/Subarray Sum Closest.java)| |Java| -|211|[Subarray Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Subarray Sum.java)| |Java| -|212|[Subset.java](https://github.com/shawnfan/LintCode/blob/master/Java/Subset.java)| |Java| -|213|[Subsets II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Subsets II.java)| |Java| -|214|[Subtree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Subtree.java)| |Java| -|215|[Swap Nodes in Pairs.java](https://github.com/shawnfan/LintCode/blob/master/Java/Swap Nodes in Pairs.java)| |Java| -|216|[Symmetric Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Symmetric Binary Tree.java)| |Java| -|217|[The Smallest Difference.java](https://github.com/shawnfan/LintCode/blob/master/Java/The Smallest Difference.java)| |Java| -|218|[Topological Sorting.java](https://github.com/shawnfan/LintCode/blob/master/Java/Topological Sorting.java)| |Java| -|219|[Total Occurrence of Target.java](https://github.com/shawnfan/LintCode/blob/master/Java/Total Occurrence of Target.java)| |Java| -|220|[Trailing Zeros.java](https://github.com/shawnfan/LintCode/blob/master/Java/Trailing Zeros.java)| |Java| -|221|[Trapping Rain Water II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Trapping Rain Water II.java)| |Java| -|222|[Trapping Rain Water.java](https://github.com/shawnfan/LintCode/blob/master/Java/Trapping Rain Water.java)| |Java| -|223|[Triangle Count.java](https://github.com/shawnfan/LintCode/blob/master/Java/Triangle Count.java)| |Java| -|224|[Tweaked Identical Binary Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Tweaked Identical Binary Tree.java)| |Java| -|225|[Two Lists Sum.java](https://github.com/shawnfan/LintCode/blob/master/Java/Two Lists Sum.java)| |Java| -|226|[Two Strings Are Anagrams.java](https://github.com/shawnfan/LintCode/blob/master/Java/Two Strings Are Anagrams.java)| |Java| -|227|[Two Sum II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Two Sum II.java)| |Java| -|228|[Ugly Number.java](https://github.com/shawnfan/LintCode/blob/master/Java/Ugly Number.java)| |Java| -|229|[Unique Binary Search Tree II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Unique Binary Search Tree II.java)| |Java| -|230|[Unique Binary Search Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Unique Binary Search Tree.java)| |Java| -|231|[Unique Characters.java](https://github.com/shawnfan/LintCode/blob/master/Java/Unique Characters.java)| |Java| -|232|[Unique Path.java](https://github.com/shawnfan/LintCode/blob/master/Java/Unique Path.java)| |Java| -|233|[Unique Paths II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Unique Paths II.java)| |Java| -|234|[Update Bits.java](https://github.com/shawnfan/LintCode/blob/master/Java/Update Bits.java)| |Java| -|235|[Valid Palindrome.java](https://github.com/shawnfan/LintCode/blob/master/Java/Valid Palindrome.java)| |Java| -|236|[Valid Parentheses.java](https://github.com/shawnfan/LintCode/blob/master/Java/Valid Parentheses.java)| |Java| -|237|[Valid Sudoku.java](https://github.com/shawnfan/LintCode/blob/master/Java/Valid Sudoku.java)| |Java| -|238|[Validate Binary Search Tree.java](https://github.com/shawnfan/LintCode/blob/master/Java/Validate Binary Search Tree.java)| |Java| -|239|[Wood Cut.java](https://github.com/shawnfan/LintCode/blob/master/Java/Wood Cut.java)| |Java| -|240|[Word Break.java](https://github.com/shawnfan/LintCode/blob/master/Java/Word Break.java)| |Java| -|241|[Word Ladder II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Word Ladder II.java)| |Java| -|242|[Word Ladder.java](https://github.com/shawnfan/LintCode/blob/master/Java/Word Ladder.java)| |Java| -|243|[Word Search II.java](https://github.com/shawnfan/LintCode/blob/master/Java/Word Search II.java)| |Java| -|244|[Word Search.java](https://github.com/shawnfan/LintCode/blob/master/Java/Word Search.java)| |Java| +### News +2017年1月17日, 陪我征战多年的 2014 MackBookPro i7 3.xGHz 被一杯清水结束了生命,在这里深切缅怀悼念。这个Git Repo是小M陪我一字一句打出来的,有过蹉跎,也有过辉煌,陪我从Day1刷题一直刷到了Day1之中。直至今日,小M记录的代码还在给广大coder带来福利。为了延续小M无私奉献的精神,我将重新在这个repo活跃起来,重整已有的问题,也会尝试总结一些System Design方面的想法,将小M还没有能够达成的梦想实现。 + +| Squence | Problem | Level | Language | Video Tutorial| +|:-------:|:--------------|:------:|:---------:|:-------------:| +|0|[2 Sum II - Input array is sorted.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum%20II%20-%20Input%20array%20is%20sorted.java)|Medium|Java|| +|1|[2 Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum%20II.java)|Medium|Java|| +|2|[2 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum.java)|Medium|Java|[Link](https://www.youtube.com/watch?v=P8zBxoVY1oI&feature=youtu.be)| +|3|[3 Sum Closest.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum%20Closest.java)|Medium|Java|| +|4|[3 Sum Smaller.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum%20Smaller.java)||Java|| +|5|[3 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum.java)|Medium|Java|| +|6|[4 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/4%20Sum.java)|Medium|Java|| +|7|[A+B.java](https://github.com/awangdev/LintCode/blob/master/Java/A+B.java)|Easy|Java|| +|8|[Add and Search Word.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20and%20Search%20Word.java)|Medium|Java|| +|9|[Add Binary.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Binary.java)|Easy|Java|| +|10|[Add Two Numbers II.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Two%20Numbers%20II.java)|Medium|Java|| +|11|[Add Two Numbers.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Two%20Numbers.java)|Easy|Java|| +|12|[Alien Dictionary.java](https://github.com/awangdev/LintCode/blob/master/Java/Alien%20Dictionary.java)|Hard|Java|| +|13|[Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Anagrams.java)|Medium|Java|| +|14|[Backpack II.java](https://github.com/awangdev/LintCode/blob/master/Java/Backpack%20II.java)|Medium|Java|| +|15|[Backpack.java](https://github.com/awangdev/LintCode/blob/master/Java/Backpack.java)|Medium|Java|| +|16|[Balanced Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Balanced%20Binary%20Tree.java)|Medium|Java|| +|17|[Best Time to Buy and Sell Stock I.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20I.java)|Medium|Java|| +|18|[Best Time to Buy and Sell Stock II.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20II.java)|Medium|Java|| +|19|[Best Time to Buy and Sell Stock III .java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20III%20.java)|Medium|Java|| +|20|[Best Time to Buy and Sell Stock IV.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20IV.java)|Hard|Java|| +|21|[Binary Representation.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Representation.java)|Hard|Java|| +|22|[Binary Search Tree Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Search%20Tree%20Iterator.java)|Hard|Java|| +|23|[Binary Tree Inorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Inorder%20Traversal.java)|Easy|Java|| +|24|[Binary Tree Level Order Traversal II.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Level%20Order%20Traversal%20II.java)|Medium|Java|| +|25|[Binary Tree Level Order Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Level%20Order%20Traversal.java)|Medium|Java|| +|26|[Binary Tree Longest Consecutive Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Longest%20Consecutive%20Sequence.java)|Medium|Java|| +|27|[Binary Tree Maximum Path Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Maximum%20Path%20Sum%20II.java)|Medium|Java|| +|28|[Binary Tree Maximum Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Maximum%20Path%20Sum.java)|Medium|Java|| +|29|[Binary Tree Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Path%20Sum.java)|Easy|Java|| +|30|[Binary Tree Paths.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Paths.java)|Easy|Java|| +|31|[Binary Tree Postorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Postorder%20Traversal.java)|Easy|Java|| +|32|[Binary Tree Preorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Preorder%20Traversal.java)|Easy|Java|| +|33|[Binary Tree Right Side View.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Right%20Side%20View.java)|Medium|Java|| +|34|[Binary Tree Serialization.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Serialization.java)|Medium|Java|| +|35|[Binary Tree Zigzag Level Order Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Zigzag%20Level%20Order%20Traversal.java)|Medium|Java|| +|36|[Building Outline.java](https://github.com/awangdev/LintCode/blob/master/Java/Building%20Outline.java)|Hard|Java|| +|37|[Burst Balloons.java](https://github.com/awangdev/LintCode/blob/master/Java/Burst%20Balloons.java)||Java|| +|38|[Change to Anagram.java](https://github.com/awangdev/LintCode/blob/master/Java/Change%20to%20Anagram.java)|Easy|Java|| +|39|[Classical Binary Search.java](https://github.com/awangdev/LintCode/blob/master/Java/Classical%20Binary%20Search.java)|Easy|Java|| +|40|[Climbing Stairs.java](https://github.com/awangdev/LintCode/blob/master/Java/Climbing%20Stairs.java)|Easy|Java|| +|41|[Clone Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Clone%20Graph.java)|Medium|Java|| +|42|[Closest Binary Search Tree Value.java](https://github.com/awangdev/LintCode/blob/master/Java/Closest%20Binary%20Search%20Tree%20Value.java)|Easy|Java|| +|43|[Closest Number in Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Closest%20Number%20in%20Sorted%20Array.java)|Easy|Java|| +|44|[Coins in a Line.java](https://github.com/awangdev/LintCode/blob/master/Java/Coins%20in%20a%20Line.java)||Java|| +|45|[ColorGrid.java](https://github.com/awangdev/LintCode/blob/master/Java/ColorGrid.java)|Medium|Java|| +|46|[Combination Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Combination%20Sum%20II.java)|Medium|Java|| +|47|[Combination Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Combination%20Sum.java)|Medium|Java|| +|48|[Combinations.java](https://github.com/awangdev/LintCode/blob/master/Java/Combinations.java)|Medium|Java|| +|49|[Compare Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Compare%20Strings.java)|Easy|Java|| +|50|[Complete Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Complete%20Binary%20Tree.java)|Easy|Java|| +|51|[Construct Binary Tree from Inorder and Postorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Construct%20Binary%20Tree%20from%20Inorder%20and%20Postorder%20Traversal.java)|Medium|Java|| +|52|[Construct Binary Tree from Inorder and Preorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Construct%20Binary%20Tree%20from%20Inorder%20and%20Preorder%20Traversal.java)|Medium|Java|| +|53|[Container With Most Water.java](https://github.com/awangdev/LintCode/blob/master/Java/Container%20With%20Most%20Water.java)||Java|| +|54|[Convert Binary Search Tree to Doubly Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Binary%20Search%20Tree%20to%20Doubly%20Linked%20List.java)|Medium|Java|| +|55|[Convert Expression to Polish Notation.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Expression%20to%20Polish%20Notation.java)|Hard|Java|| +|56|[Convert Expression to Reverse Polish Notation.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Expression%20to%20Reverse%20Polish%20Notation.java)|Hard|Java|| +|57|[Convert Integer A to Integer B.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Integer%20A%20to%20Integer%20B.java)|Easy|Java|| +|58|[Convert Sorted Array to Binary Search Tree With Minimal Height.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Sorted%20Array%20to%20Binary%20Search%20Tree%20With%20Minimal%20Height.java)|Easy|Java|| +|59|[Convert Sorted List to Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Sorted%20List%20to%20Binary%20Search%20Tree.java)|Medium|Java|| +|60|[Copy List with Random Pointer.java](https://github.com/awangdev/LintCode/blob/master/Java/Copy%20List%20with%20Random%20Pointer.java)|Medium|Java|| +|61|[Cosine Similarity.java](https://github.com/awangdev/LintCode/blob/master/Java/Cosine%20Similarity.java)|Easy|Java|| +|62|[Count 1 in Binary.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%201%20in%20Binary.java)|Easy|Java|| +|63|[Count and Say.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20and%20Say.java)|Easy|Java|| +|64|[Count of Smaller Number before itself.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20of%20Smaller%20Number%20before%20itself.java)|Hard|Java|| +|65|[Count of Smaller Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20of%20Smaller%20Number.java)|Medium|Java|| +|66|[Count Primes.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20Primes.java)|Easy|Java|| +|67|[Course Schedule II.java](https://github.com/awangdev/LintCode/blob/master/Java/Course%20Schedule%20II.java)|Medium|Java|| +|68|[Course Schedule.java](https://github.com/awangdev/LintCode/blob/master/Java/Course%20Schedule.java)|Medium|Java|| +|69|[Data Stream Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Data%20Stream%20Median.java)|Hard|Java|| +|70|[Delete Digits.java](https://github.com/awangdev/LintCode/blob/master/Java/Delete%20Digits.java)|Medium|Java|| +|71|[Delete Node in the Middle of Singly Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Delete%20Node%20in%20the%20Middle%20of%20Singly%20Linked%20List.java)|Easy|Java|| +|72|[Distinct Subsequences.java](https://github.com/awangdev/LintCode/blob/master/Java/Distinct%20Subsequences.java)|Hard|Java|| +|73|[Edit Distance.java](https://github.com/awangdev/LintCode/blob/master/Java/Edit%20Distance.java)|Medium|Java|| +|74|[Encode and Decode Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Encode%20and%20Decode%20Strings.java)|Medium|Java|| +|75|[ExcelSheetColumnNumber .java](https://github.com/awangdev/LintCode/blob/master/Java/ExcelSheetColumnNumber%20.java)|Easy|Java|| +|76|[Expression Evaluation.java](https://github.com/awangdev/LintCode/blob/master/Java/Expression%20Evaluation.java)|Hard|Java|| +|77|[Expression Tree Build.java](https://github.com/awangdev/LintCode/blob/master/Java/Expression%20Tree%20Build.java)|Hard|Java|| +|78|[Fast Power.java](https://github.com/awangdev/LintCode/blob/master/Java/Fast%20Power.java)|Medium|Java|| +|79|[Fibonacci.java](https://github.com/awangdev/LintCode/blob/master/Java/Fibonacci.java)|Easy|Java|| +|80|[Find Minimum in Rotated Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Minimum%20in%20Rotated%20Sorted%20Array%20II.java)||Java|| +|81|[Find Minimum in Rotated Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Minimum%20in%20Rotated%20Sorted%20Array.java)||Java|| +|82|[Find Peak Element II.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Peak%20Element%20II.java)||Java|| +|83|[Find Peak Element.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Peak%20Element.java)||Java|| +|84|[Find the Connected Component in the Undirected Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20the%20Connected%20Component%20in%20the%20Undirected%20Graph.java)|Medium|Java|| +|85|[Find the Weak Connected Component in the Directed Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20the%20Weak%20Connected%20Component%20in%20the%20Directed%20Graph.java)|Medium|Java|| +|86|[First Bad Version.java](https://github.com/awangdev/LintCode/blob/master/Java/First%20Bad%20Version.java)|Medium|Java|| +|87|[First Missing Positive.java](https://github.com/awangdev/LintCode/blob/master/Java/First%20Missing%20Positive.java)||Java|| +|88|[Flatten 2D Vector.java](https://github.com/awangdev/LintCode/blob/master/Java/Flatten%202D%20Vector.java)||Java|| +|89|[Flatten Binary Tree to Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Flatten%20Binary%20Tree%20to%20Linked%20List.java)|Easy|Java|| +|90|[Flattern 2D Vector.java](https://github.com/awangdev/LintCode/blob/master/Java/Flattern%202D%20Vector.java)||Java|| +|91|[Flip Game II.java](https://github.com/awangdev/LintCode/blob/master/Java/Flip%20Game%20II.java)||Java|| +|92|[Flip Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Flip%20Game.java)||Java|| +|93|[Fraction to Recurring Decimal.java](https://github.com/awangdev/LintCode/blob/master/Java/Fraction%20to%20Recurring%20Decimal.java)||Java|| +|94|[Game of Life.java](https://github.com/awangdev/LintCode/blob/master/Java/Game%20of%20Life.java)||Java|| +|95|[Gas Station.java](https://github.com/awangdev/LintCode/blob/master/Java/Gas%20Station.java)||Java|| +|96|[Generate Parentheses.java](https://github.com/awangdev/LintCode/blob/master/Java/Generate%20Parentheses.java)||Java|| +|97|[Graph Valid Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Graph%20Valid%20Tree.java)|Medium|Java|| +|98|[Gray Code.java](https://github.com/awangdev/LintCode/blob/master/Java/Gray%20Code.java)|Medium|Java|| +|99|[Group Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Group%20Anagrams.java)|Medium|Java|| +|100|[Group Shifted Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Group%20Shifted%20Strings.java)|Easy|Java|| +|101|[H-Index II.java](https://github.com/awangdev/LintCode/blob/master/Java/H-Index%20II.java)||Java|| +|102|[H-Index.java](https://github.com/awangdev/LintCode/blob/master/Java/H-Index.java)||Java|| +|103|[Happy Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Happy%20Number.java)|Easy|Java|| +|104|[Hash Function.java](https://github.com/awangdev/LintCode/blob/master/Java/Hash%20Function.java)|Easy|Java|| +|105|[HashHeap.java](https://github.com/awangdev/LintCode/blob/master/Java/HashHeap.java)|Hard|Java|| +|106|[HashWithArray.java](https://github.com/awangdev/LintCode/blob/master/Java/HashWithArray.java)|Easy|Java|| +|107|[HashWithCustomizedClass(LinkedList).java](https://github.com/awangdev/LintCode/blob/master/Java/HashWithCustomizedClass(LinkedList).java)|Medium|Java|| +|108|[Heapify.java](https://github.com/awangdev/LintCode/blob/master/Java/Heapify.java)|Medium|Java|| +|109|[House Robber II.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber%20II.java)|Medium|Java|| +|110|[House Robber III.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber%20III.java)|Hard|Java|| +|111|[House Robber.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber.java)|Easy|Java|| +|112|[Identical Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Identical%20Binary%20Tree.java)|Easy|Java|| +|113|[Implement Queue by Two Stacks.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Queue%20by%20Two%20Stacks.java)||Java|| +|114|[Implement Stack by Two Queues.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Stack%20by%20Two%20Queues.java)||Java|| +|115|[Implement Stack.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Stack.java)||Java|| +|116|[Implement strStr().java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20strStr().java)||Java|| +|117|[Implement Trie (Prefix Tree).java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Trie%20(Prefix%20Tree).java)||Java|| +|118|[Implement Trie.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Trie.java)|Medium|Java|| +|119|[IndexMatch.java](https://github.com/awangdev/LintCode/blob/master/Java/IndexMatch.java)|Easy|Java|| +|120|[Inorder Successor in Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Inorder%20Successor%20in%20Binary%20Search%20Tree.java)|Medium|Java|| +|121|[Insert Interval.java](https://github.com/awangdev/LintCode/blob/master/Java/Insert%20Interval.java)|Easy|Java|| +|122|[Insert Node in a Binary Search Tree .java](https://github.com/awangdev/LintCode/blob/master/Java/Insert%20Node%20in%20a%20Binary%20Search%20Tree%20.java)|Easy|Java|| +|123|[Insertion Sort List.java](https://github.com/awangdev/LintCode/blob/master/Java/Insertion%20Sort%20List.java)||Java|| +|124|[Integer to English Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Integer%20to%20English%20Words.java)||Java|| +|125|[Interleaving Positive and Negative Numbers.java](https://github.com/awangdev/LintCode/blob/master/Java/Interleaving%20Positive%20and%20Negative%20Numbers.java)||Java|| +|126|[Interleaving String.java](https://github.com/awangdev/LintCode/blob/master/Java/Interleaving%20String.java)||Java|| +|127|[Intersection of Two Linked Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Intersection%20of%20Two%20Linked%20Lists.java)|Easy|Java|| +|128|[Interval Minimum Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Minimum%20Number.java)|Medium|Java|| +|129|[Interval Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Sum%20II.java)|Hard|Java|| +|130|[Interval Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Sum.java)|Medium|Java|| +|131|[Invert Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Invert%20Binary%20Tree.java)|Easy|Java|| +|132|[Isomorphic Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Isomorphic%20Strings.java)|Easy|Java|| +|133|[Jump Game II.java](https://github.com/awangdev/LintCode/blob/master/Java/Jump%20Game%20II.java)|Hard|Java|| +|134|[Jump Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Jump%20Game.java)|Medium|Java|| +|135|[Kth Largest Element.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Largest%20Element.java)|Medium|Java|| +|136|[Kth Smallest Element in a BST.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Smallest%20Element%20in%20a%20BST.java)||Java|| +|137|[Kth Smallest Number in Sorted Matrix.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Smallest%20Number%20in%20Sorted%20Matrix.java)|Medium|Java|| +|138|[Kth Smallest Sum In Two Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Smallest%20Sum%20In%20Two%20Sorted%20Arrays.java)|Hard|Java|| +|139|[Largest Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Largest%20Number.java)||Java|| +|140|[Largest Rectangle in Histogram.java](https://github.com/awangdev/LintCode/blob/master/Java/Largest%20Rectangle%20in%20Histogram.java)||Java|| +|141|[Last Position of Target.java](https://github.com/awangdev/LintCode/blob/master/Java/Last%20Position%20of%20Target.java)||Java|| +|142|[Length of Last Word.java](https://github.com/awangdev/LintCode/blob/master/Java/Length%20of%20Last%20Word.java)||Java|| +|143|[Letter Combinations of a Phone Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Letter%20Combinations%20of%20a%20Phone%20Number.java)|Medium|Java|| +|144|[Linked List Cycle II.java](https://github.com/awangdev/LintCode/blob/master/Java/Linked%20List%20Cycle%20II.java)||Java|| +|145|[Linked List Cycle.java](https://github.com/awangdev/LintCode/blob/master/Java/Linked%20List%20Cycle.java)||Java|| +|146|[Longest Common Prefix.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Prefix.java)|Medium|Java|| +|147|[Longest Common Subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Subsequence.java)||Java|| +|148|[Longest Common Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Substring.java)||Java|| +|149|[Longest Consecutive Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Consecutive%20Sequence.java)||Java|| +|150|[Longest Increasing Continuous subsequence II.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Continuous%20subsequence%20II.java)||Java|| +|151|[Longest Increasing Continuous subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Continuous%20subsequence.java)||Java|| +|152|[Longest Increasing Subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Subsequence.java)||Java|| +|153|[Longest Palindromic Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Palindromic%20Substring.java)|Medium|Java|| +|154|[Longest Substring with At Most K Distinct Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Substring%20with%20At%20Most%20K%20Distinct%20Characters.java)|Medium|Java|| +|155|[Longest Substring Without Repeating Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Substring%20Without%20Repeating%20Characters.java)|Medium|Java|| +|156|[Longest Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Words.java)||Java|| +|157|[Lowest Common Ancestor II.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor%20II.java)|Easy|Java|| +|158|[Lowest Common Ancestor of a Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Search%20Tree.java)|Medium|Java|| +|159|[Lowest Common Ancestor.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor.java)|Easy|Java|| +|160|[LRU Cache.java](https://github.com/awangdev/LintCode/blob/master/Java/LRU%20Cache.java)|Hard|Java|| +|161|[Majority Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number%20II.java)|Medium|Java|| +|162|[Majority Number III.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number%20III.java)|Medium|Java|| +|163|[Majority Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number.java)|Easy|Java|| +|164|[Matrix Zigzag Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Matrix%20Zigzag%20Traversal.java)|Easy|Java|| +|165|[Max Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Max%20Tree.java)|Hard|Java|| +|166|[Maximal Square.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximal%20Square.java)|Medium|Java|| +|167|[Maximum Depth of Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Depth%20of%20Binary%20Tree.java)|Easy|Java|| +|168|[Maximum Product Subarray.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Product%20Subarray.java)||Java|| +|169|[Maximum Subarray III.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Subarray%20III.java)||Java|| +|170|[MaximumSubarray.java](https://github.com/awangdev/LintCode/blob/master/Java/MaximumSubarray.java)||Java|| +|171|[MaximumSubarrayII.java](https://github.com/awangdev/LintCode/blob/master/Java/MaximumSubarrayII.java)||Java|| +|172|[Median of two Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Median%20of%20two%20Sorted%20Arrays.java)|Hard|Java|| +|173|[Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Median.java)||Java|| +|174|[Meeting Rooms II.java](https://github.com/awangdev/LintCode/blob/master/Java/Meeting%20Rooms%20II.java)|Medium|Java|| +|175|[Meeting Rooms.java](https://github.com/awangdev/LintCode/blob/master/Java/Meeting%20Rooms.java)|Easy|Java|| +|176|[Merge Intervals.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Intervals.java)|Easy|Java|| +|177|[Merge k Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20k%20Sorted%20Arrays.java)|Medium|Java|| +|178|[Merge k Sorted Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20k%20Sorted%20Lists.java)|Medium|Java|| +|179|[Merge Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Sorted%20Array%20II.java)||Java|| +|180|[Merge Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Sorted%20Array.java)|Easy|Java|| +|181|[Merge Two Sorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Two%20Sorted%20List.java)|Easy|Java|| +|182|[Merge Two Sorted Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Two%20Sorted%20Lists.java)||Java|| +|183|[Middle of Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Middle%20of%20Linked%20List.java)||Java|| +|184|[Min Stack.java](https://github.com/awangdev/LintCode/blob/master/Java/Min%20Stack.java)|Easy|Java|| +|185|[Minimum Height Trees.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Height%20Trees.java)||Java|| +|186|[Minimum Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Path%20Sum.java)||Java|| +|187|[Minimum Size Subarray Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Size%20Subarray%20Sum.java)|Medium|Java|| +|188|[Minimum Subarray.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Subarray.java)||Java|| +|189|[Minimum Window Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Window%20Substring.java)|Hard|Java|| +|190|[MinimumDepthOfBinaryTree.java](https://github.com/awangdev/LintCode/blob/master/Java/MinimumDepthOfBinaryTree.java)|Easy|Java|| +|191|[Missing Ranges.java](https://github.com/awangdev/LintCode/blob/master/Java/Missing%20Ranges.java)||Java|| +|192|[Multiply Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Multiply%20Strings.java)|Medium|Java|| +|193|[Next Permutation.java](https://github.com/awangdev/LintCode/blob/master/Java/Next%20Permutation.java)|Medium|Java|| +|194|[Nim Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Nim%20Game.java)||Java|| +|195|[NQueens.java](https://github.com/awangdev/LintCode/blob/master/Java/NQueens.java)||Java|| +|196|[NQueensII.java](https://github.com/awangdev/LintCode/blob/master/Java/NQueensII.java)||Java|| +|197|[Nth to Last Node in List.java](https://github.com/awangdev/LintCode/blob/master/Java/Nth%20to%20Last%20Node%20in%20List.java)||Java|| +|198|[Number of Airplane in the sky.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Airplane%20in%20the%20sky.java)|Medium|Java|| +|199|[Number of Islands II.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Islands%20II.java)|Hard|Java|| +|200|[Number of Islands.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Islands.java)|Medium|Java|| +|201|[Number Triangles.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20Triangles.java)||Java|| +|202|[O(1) Check Power of 2.java](https://github.com/awangdev/LintCode/blob/master/Java/O(1)%20Check%20Power%20of%202.java)||Java|| +|203|[One Edit Distance.java](https://github.com/awangdev/LintCode/blob/master/Java/One%20Edit%20Distance.java)|Medium|Java|| +|204|[Paint Fence.java](https://github.com/awangdev/LintCode/blob/master/Java/Paint%20Fence.java)||Java|| +|205|[Palindrome Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Linked%20List.java)||Java|| +|206|[Palindrome Partitioning II.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Partitioning%20II.java)||Java|| +|207|[Palindrome Partitioning.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Partitioning.java)||Java|| +|208|[Palindrome Permutation II.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Permutation%20II.java)|Medium|Java|| +|209|[Palindrome Permutation.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Permutation.java)|Easy|Java|| +|210|[Partition Array by Odd and Even.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20Array%20by%20Odd%20and%20Even.java)||Java|| +|211|[Partition Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20Array.java)||Java|| +|212|[Partition List.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20List.java)||Java|| +|213|[Pascal's Triangle II.java](https://github.com/awangdev/LintCode/blob/master/Java/Pascal's%20Triangle%20II.java)|Easy|Java|| +|214|[Peeking Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Peeking%20Iterator.java)||Java|| +|215|[Perfect Squares.java](https://github.com/awangdev/LintCode/blob/master/Java/Perfect%20Squares.java)||Java|| +|216|[Permutation Index.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutation%20Index.java)|Easy|Java|| +|217|[Permutation Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutation%20Sequence.java)|Medium|Java|| +|218|[Permutations II.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutations%20II.java)|Medium|Java|| +|219|[Permutations.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutations.java)|Medium|Java|| +|220|[Plus One.java](https://github.com/awangdev/LintCode/blob/master/Java/Plus%20One.java)||Java|| +|221|[Populating Next Right Pointers in Each Node II.java](https://github.com/awangdev/LintCode/blob/master/Java/Populating%20Next%20Right%20Pointers%20in%20Each%20Node%20II.java)|Hard|Java|| +|222|[Populating Next Right Pointers in Each Node.java](https://github.com/awangdev/LintCode/blob/master/Java/Populating%20Next%20Right%20Pointers%20in%20Each%20Node.java)|Medium|Java|| +|223|[Pow(x,n).java](https://github.com/awangdev/LintCode/blob/master/Java/Pow(x,n).java)||Java|| +|224|[Power of Three.java](https://github.com/awangdev/LintCode/blob/master/Java/Power%20of%20Three.java)|Easy|Java|| +|225|[Product of Array Exclude Itself.java](https://github.com/awangdev/LintCode/blob/master/Java/Product%20of%20Array%20Exclude%20Itself.java)||Java|| +|226|[QuickSort.java](https://github.com/awangdev/LintCode/blob/master/Java/QuickSort.java)|Easy|Java|| +|227|[Recover Rotated Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Recover%20Rotated%20Sorted%20Array.java)||Java|| +|228|[Rehashing.java](https://github.com/awangdev/LintCode/blob/master/Java/Rehashing.java)|Medium|Java|| +|229|[Remove Duplicates from Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20Array.java)||Java|| +|230|[Remove Duplicates from Sorted List II.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20List%20II.java)||Java|| +|231|[Remove Duplicates from Sorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20List.java)||Java|| +|232|[Remove Duplicates from Unsorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Unsorted%20List.java)||Java|| +|233|[Remove Linked List Elements.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Linked%20List%20Elements.java)||Java|| +|234|[Remove Node in Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Node%20in%20Binary%20Search%20Tree.java)|Hard|Java|| +|235|[Remove Nth Node From End of List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Nth%20Node%20From%20End%20of%20List.java)||Java|| +|236|[Reorder List.java](https://github.com/awangdev/LintCode/blob/master/Java/Reorder%20List.java)||Java|| +|237|[Restore IP Addresses.java](https://github.com/awangdev/LintCode/blob/master/Java/Restore%20IP%20Addresses.java)||Java|| +|238|[Reverse Integer.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Integer.java)||Java|| +|239|[Reverse Linked List II .java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Linked%20List%20II%20.java)||Java|| +|240|[Reverse Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Linked%20List.java)|Easy|Java|| +|241|[Reverse Words in a String II.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Words%20in%20a%20String%20II.java)|Medium|Java|| +|242|[Reverse Words in a String.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Words%20in%20a%20String.java)|Medium|Java|| +|243|[reverseInteger.java](https://github.com/awangdev/LintCode/blob/master/Java/reverseInteger.java)||Java|| +|244|[Roman to Integer.java](https://github.com/awangdev/LintCode/blob/master/Java/Roman%20to%20Integer.java)|Easy|Java|| +|245|[Rotate Image.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20Image.java)|Medium|Java|| +|246|[Rotate List.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20List.java)||Java|| +|247|[Rotate String.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20String.java)||Java|| +|248|[Search a 2D Matrix II.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20a%202D%20Matrix%20II.java)||Java|| +|249|[Search a 2D Matrix.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20a%202D%20Matrix.java)||Java|| +|250|[Search for a Range.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20for%20a%20Range.java)||Java|| +|251|[Search Insert Position.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Insert%20Position.java)||Java|| +|252|[Search Range in Binary Search Tree .java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Range%20in%20Binary%20Search%20Tree%20.java)|Medium|Java|| +|253|[Search Rotated in Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Rotated%20in%20Sorted%20Array%20II.java)||Java|| +|254|[Search Rotated in Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Rotated%20in%20Sorted%20Array.java)|Hard|Java|| +|255|[Segment Tree Build II.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Build%20II.java)|Medium|Java|| +|256|[Segment Tree Build.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Build.java)|Medium|Java|| +|257|[Segment Tree Modify.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Modify.java)|Medium|Java|| +|258|[Segment Tree Query II.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Query%20II.java)|Medium|Java|| +|259|[Segment Tree Query.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Query.java)|Medium|Java|| +|260|[Serilization and Deserialization Of Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Serilization%20and%20Deserialization%20Of%20Binary%20Tree.java)||Java|| +|261|[Single Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number%20II.java)||Java|| +|262|[Single Number III.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number%20III.java)||Java|| +|263|[Single Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number.java)||Java|| +|264|[Singleton.java](https://github.com/awangdev/LintCode/blob/master/Java/Singleton.java)||Java|| +|265|[Sliding Window Maximum.java](https://github.com/awangdev/LintCode/blob/master/Java/Sliding%20Window%20Maximum.java)||Java|| +|266|[Sliding Window Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Sliding%20Window%20Median.java)||Java|| +|267|[Sort Color.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Color.java)||Java|| +|268|[Sort Colors II.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Colors%20II.java)||Java|| +|269|[Sort Letters by Case.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Letters%20by%20Case.java)||Java|| +|270|[Sort List.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20List.java)||Java|| +|271|[Space Replacement.java](https://github.com/awangdev/LintCode/blob/master/Java/Space%20Replacement.java)||Java|| +|272|[Sqrt(x).java](https://github.com/awangdev/LintCode/blob/master/Java/Sqrt(x).java)||Java|| +|273|[Stone Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Stone%20Game.java)||Java|| +|274|[String to Integer(atoi).java](https://github.com/awangdev/LintCode/blob/master/Java/String%20to%20Integer(atoi).java)|Easy|Java|| +|275|[Strobogrammatic Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Strobogrammatic%20Number%20II.java)||Java|| +|276|[Strobogrammatic Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Strobogrammatic%20Number.java)||Java|| +|277|[StrStr.java](https://github.com/awangdev/LintCode/blob/master/Java/StrStr.java)||Java|| +|278|[Subarray Sum Closest.java](https://github.com/awangdev/LintCode/blob/master/Java/Subarray%20Sum%20Closest.java)|Medium|Java|| +|279|[Subarray Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Subarray%20Sum.java)|Easy|Java|| +|280|[Subset.java](https://github.com/awangdev/LintCode/blob/master/Java/Subset.java)|Medium|Java|| +|281|[Subsets II.java](https://github.com/awangdev/LintCode/blob/master/Java/Subsets%20II.java)|Medium|Java|| +|282|[Subtree.java](https://github.com/awangdev/LintCode/blob/master/Java/Subtree.java)|Easy|Java|| +|283|[Summary Ranges.java](https://github.com/awangdev/LintCode/blob/master/Java/Summary%20Ranges.java)||Java|| +|284|[Surrounded Regions.java](https://github.com/awangdev/LintCode/blob/master/Java/Surrounded%20Regions.java)||Java|| +|285|[Swap Nodes in Pairs.java](https://github.com/awangdev/LintCode/blob/master/Java/Swap%20Nodes%20in%20Pairs.java)||Java|| +|286|[Symmetric Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Symmetric%20Binary%20Tree.java)|Easy|Java|| +|287|[The Smallest Difference.java](https://github.com/awangdev/LintCode/blob/master/Java/The%20Smallest%20Difference.java)||Java|| +|288|[Top K Frequent Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Top%20K%20Frequent%20Words.java)|Medium|Java|| +|289|[Topological Sorting.java](https://github.com/awangdev/LintCode/blob/master/Java/Topological%20Sorting.java)|Medium|Java|| +|290|[Total Occurrence of Target.java](https://github.com/awangdev/LintCode/blob/master/Java/Total%20Occurrence%20of%20Target.java)||Java|| +|291|[Trailing Zeros.java](https://github.com/awangdev/LintCode/blob/master/Java/Trailing%20Zeros.java)||Java|| +|292|[Trapping Rain Water II.java](https://github.com/awangdev/LintCode/blob/master/Java/Trapping%20Rain%20Water%20II.java)|Hard|Java|| +|293|[Trapping Rain Water.java](https://github.com/awangdev/LintCode/blob/master/Java/Trapping%20Rain%20Water.java)|Medium|Java|| +|294|[Triangle Count.java](https://github.com/awangdev/LintCode/blob/master/Java/Triangle%20Count.java)||Java|| +|295|[Tweaked Identical Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Tweaked%20Identical%20Binary%20Tree.java)|Easy|Java|| +|296|[Two Lists Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Two%20Lists%20Sum.java)||Java|| +|297|[Two Strings Are Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Two%20Strings%20Are%20Anagrams.java)|Easy|Java|| +|298|[Ugly Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Ugly%20Number%20II.java)||Java|| +|299|[Ugly Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Ugly%20Number.java)|Medium|Java|| +|300|[Unique Binary Search Tree II.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Binary%20Search%20Tree%20II.java)||Java|| +|301|[Unique Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Binary%20Search%20Tree.java)||Java|| +|302|[Unique Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Characters.java)||Java|| +|303|[Unique Path.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Path.java)|Medium|Java|| +|304|[Unique Paths II.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Paths%20II.java)||Java|| +|305|[Unique Word Abbreviation.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Word%20Abbreviation.java)||Java|| +|306|[Update Bits.java](https://github.com/awangdev/LintCode/blob/master/Java/Update%20Bits.java)||Java|| +|307|[Valid Anagram.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Anagram.java)||Java|| +|308|[Valid Palindrome.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Palindrome.java)|Easy|Java|[Link](https://www.youtube.com/watch?v=2hNK0Yz53LQ&list=PLZn-UvluQZuNedn1hDzTmNLE8MQWXjKVb)| +|309|[Valid Parentheses.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Parentheses.java)|Easy|Java|| +|310|[Valid Sudoku.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Sudoku.java)|Easy|Java|| +|311|[Validate Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Validate%20Binary%20Search%20Tree.java)|Medium|Java|| +|312|[Wiggle Sort.java](https://github.com/awangdev/LintCode/blob/master/Java/Wiggle%20Sort.java)||Java|| +|313|[Wood Cut.java](https://github.com/awangdev/LintCode/blob/master/Java/Wood%20Cut.java)||Java|| +|314|[Word Break II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Break%20II.java)|Hard|Java|| +|315|[Word Break.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Break.java)|Medium|Java|| +|316|[Word Ladder II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Ladder%20II.java)|Hard|Java|| +|317|[Word Ladder.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Ladder.java)|Medium|Java|| +|318|[Word Pattern.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Pattern.java)|Easy|Java|| +|319|[Word Search II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Search%20II.java)|Hard|Java|| +|320|[Word Search.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Search.java)|Medium|Java|| +|321|[Zigzag Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Zigzag%20Iterator.java)||Java|| diff --git a/ReviewPage.md b/ReviewPage.md new file mode 100644 index 0000000..e0d130a --- /dev/null +++ b/ReviewPage.md @@ -0,0 +1,6890 @@ +# Review Page + +This page summarize the solutions of all problems. For thoughts,ideas written in English, refer to deach individual solution. +New problems will be automatically updated once added. + +**0. [2 Sum II - Input array is sorted.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum%20II%20-%20Input%20array%20is%20sorted.java)** Level: Medium + +排序好的array. Binary Search移动start和end,核查sum。 + + + +--- +**1. [2 Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum%20II.java)** Level: Medium + +LintCode的题. 注意找的是greater/bigger than target。 + +由于给定条件允许O(nLogn): + sort + two pointer + +while里面two pointer移动。每次如果num[left]+num[right] > target,那么其中所有num[left++]的加上num[right]都>target. +也就是,num[right]不动,计算加入挪动left能有多少组,那就是: right-left这么多。 全部加到count上去。 +然后right--.换个right去和前面的left部分作比较。 + + +--- +**2. [2 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/2%20Sum.java)** Level: Medium + [Tutorial Link](https://www.youtube.com/watch?v=P8zBxoVY1oI&feature=youtu.be) + +解法1:相对暴力简洁, HashMap,找到一个value, 存一个; 若在HashMap里面 match 到结果, 就return HashMap里存的index. O(n) space && time. + +解法2:Sort array, two pointer 前后++,--搜索。Sort 用时O(nlogn). +1. 第一步 two pointer 找 value. +2. 注意,要利用额外的空间保留original array, 用来时候找index. (此处不能用HashMap,因为以value 为key,但value可能重复) +O(n) space, O(nlogn) time. + + + +--- +**3. [3 Sum Closest.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum%20Closest.java)** Level: Medium + +3Sum 的一种简单形式, 并且都没有找index, value, 而只是找个sum罢了. + +double for loop。 2Sum只能用土办法 left/right 2 pointers。 O(n^2) + +注意:check closest时候用long, 以免int不够用 + + +--- +**4. [3 Sum Smaller.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum%20Smaller.java)** +发现j,k满足条件时候,(k - j)就是所有 sum target, 又因为j不能后退,只能k--,那么问题就被锁定了. 这样可以做到O(n2) + +--- +**5. [3 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/3%20Sum.java)** Level: Medium + +用个for loop 加上 2sum 的土办法。 + +注意: + 1. 找 value triplets, 多个结果。注意,并非找index。 + 2. 要升序, 第一层for loop 从最后一个元素挑起, 保证了顺序。 + 3. 去掉duplicate: check用过的同样的数字,都跳掉。不需要用同样的数字再计算一边已有结果。 + +步骤: + 1. For loop 挑个数字A. + 2. 2Sum 出一堆2个数字的结果 + 3. Cross match 步骤1里面的A. + +时间 O(n^2), 两个nested loop + + +另外, 还是可以用HashMap来做2Sum。稍微短点。还是要注意handle duplicates. + +再另外(leetcode做时写的):先sort,然后two pointer。 + + +--- +**6. [4 Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/4%20Sum.java)** Level: Medium + +方法1: 3Sum外面再加一层. 参考3Sum. 时间O(n^3)。 但此方法在k-sum时候,无疑过于费时间. O(n^k) + +方法2: 参见 http://lifexplorer.me/leetcode-3sum-4sum-and-k-sum/ + 1. 利用2Sum的原理,把4Sum分为连个2Sum。左一个pair,右一个pair,每个pair里面放2个数字。 + 2. 以一个点,i,作为分界口,也要列举出所有i之前的pair,作为基础。 + 3. 再尝试从所有i+1后面,找合适的2nd pair。 + + 注意:在造class Pair时候,要做@override的function: hashCode(), equals(Object d). 平时不太想得起来用。 + + +--- +**7. [A+B.java](https://github.com/awangdev/LintCode/blob/master/Java/A+B.java)** Level: Easy + +^ 是不完全加法. 每次都忽略了进位。而 & 刚好可以算出需要的所有进位。 + +那么就,首先记录好进位的数字:carry. 然后 a^b 不完全加法一次。然后b用来放剩下的carry, 每次移动一位,继续加,知道b循环为0为止。 + +Bit Operation +Steps: + a & b: 每bit可能出得余数 + a ^ b: 每bit在此次操作可能留下的值,XOR 操作 + 每次左移余数1位,然后存到b, 再去跟a做第一步。loop until b == 0 + +(http://www.meetqun.com/thread-6580-1-1.html) + + +--- +**8. [Add and Search Word.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20and%20Search%20Word.java)** Level: Medium + +Trie结构, prefix tree的变形: '.'可以代替任何字符,那么就要iterate这个node所有的children. + +节点里面有char, isEnd, HashMap +Build trie = Insert word:没node就加,有node就移动。 +Search word:没有node就报错. 到结尾return true + +这题因为'.'可以代替任何possible的字符,没一种都是一个新的path,所以recursive做比较好些。 +(iterative就要queue了,麻烦点) + + +--- +**9. [Add Binary.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Binary.java)** Level: Easy + +方法一:土办法没技术,把binary换成数字,加起来,再换成binary。如果input很大,那么很可能int,long都hold不住。不保险。 + +方法二:一般方法,string化为charArray,然后逐位加起,最后记得处理多余的一个carry on + + + +--- +**10. [Add Two Numbers II.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Two%20Numbers%20II.java)** Level: Medium + +LinkedList并没有反过来,那么自己反: + 方向相反。巧用stack. + +做加法都一样: + 1. carrier + 2. carrier = (rst + carrier) / 10 + 3. rst = (rst + carrier) % 10 + + +--- +**11. [Add Two Numbers.java](https://github.com/awangdev/LintCode/blob/master/Java/Add%20Two%20Numbers.java)** Level: Easy + +LinkedList都已经反转好了,直接做。 + +遍历两个l1,l2把carry-on处理好,每次生成一个新node,最后检查carry-on。 + +跟Add Binary的理解方式一模一样。 + + + +--- +**12. [Alien Dictionary.java](https://github.com/awangdev/LintCode/blob/master/Java/Alien%20Dictionary.java)** Level: Hard + +Not Done yet。 Topological sort. + + +--- +**13. [Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Anagrams.java)** Level: Medium + + +1. HashMap 的做法. sort每个string, 存进HashMap, 重复的就是anagrams,最后输出。 + toCharArray + Arrays.sort + Stirng.valueOf(char[]) + 时间n*L*O(logL),L是最长string的长度。 + +2. Arrays.toString(arr)的做法。arr是int[26], assuming only have 26 lowercase letters. +Count occurrance, 然后convert to String,作为map的key. +Time complexity: nO(L) + +3. 另一种做法:http://www.jiuzhang.com/solutions/anagrams/ + 1. take each string, count the occurrance of the 26 letters. save in int[]count. + 2. hash the int[] count and output a unique hash value. + hash = hash * a + num + a = a * b. + 3. save to hashmap in the same way as we do. + +这一步把for s: strs 里面的时间复杂度降到了O(L). L = s.length(). +Need to work on the getHash() function. + +时间变成n*O(L). Better. + + + +--- +**14. [Backpack II.java](https://github.com/awangdev/LintCode/blob/master/Java/Backpack%20II.java)** Level: Medium + +做了Backpack I, 这个就如出一辙。 +想法还是,选了A[i-1] 或者没选A[i]. +一路往前跑不回头。就出来了。 +其实这个Backpack II 还更容易看懂代码。 + +O(m)的做法: +想想,的确我们只care 最后一行,所以一个存value的就够了。 +注意:和bakcpackI的 O(m)一样的,j是倒序的。如果没有更好的j,就不要更新。就是这个道理。 + + + +--- +**15. [Backpack.java](https://github.com/awangdev/LintCode/blob/master/Java/Backpack.java)** Level: Medium + +DP。 + row是item大小: 0, A[0], A[1] ... A[A.length -1] + col是背包累积的size: 0, 1, 2, ... m. + +想法: + dp[i][j]有这么i-1个item, 用他们可否组成size为j的背包?true/false. (反过来考虑了,不是想是否超过size j, 而是考虑是否能拼出exact size == j)。 + 注意注意:虽然dp里面一直存在i的位置,实际上考虑的是在i位置的时候,看前i-1个item. + +看一遍code,会发现: + 1. picked A[i-1]: 如果上一个item, A[i-1],被加了上来, 用j-A[i-1]看看,是否这再前一步也true. true就好啦。 + 2. did not pick A[i-1]: 那就是说,不加上A[i-1], 上一行d[i-1][j]还是需要是true。 + +最后: + 跑一边dp 最下面一个row. 从末尾开始找,最末尾的一个j (能让dp[i][j] == true)的,就是最多能装的大小 :) + +时间,空间都是:O(mn) + + + +再有: +O(m)时间的做法,具体看solution. 注意j是倒序的啊! +依然是O(mn)的空间 + + + +--- +**16. [Balanced Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Balanced%20Binary%20Tree.java)** Level: Medium + +1. DFS using depth marker: 每个depth都存一下。然后如果有不符合条件的,存为-1. + 一旦有-1, 就全部返回。 + 最后比较返回结果是不是-1. 是-1,那就false. + Traverse 整个tree, O(n) + +2. Only calculate depth using maxDepth function. Same concept as in 1, but cost more traversal efforts. + + +--- +**17. [Best Time to Buy and Sell Stock I.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20I.java)** Level: Medium + +理解意思是关键: + 每天都就交易价格,n天只让买卖一次,那就找个最低价买进,找个最高价卖出。 + 记录每天最小值Min是多少。O(n) + 每天都算和当下的Min买卖,profit最大多少。 + + + +--- +**18. [Best Time to Buy and Sell Stock II.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20II.java)** Level: Medium + +和Stock I 的区别:可以买卖多次,求总和的最大盈利。 + +找涨幅最大的区间,买卖: +找到低谷,买进:peek = start + 1 时候,就是每次往前走一步;若没有上涨趋势,继续往低谷前进。 +涨到峰顶,卖出:一旦有上涨趋势,进一个while loop,涨到底, 再加个profit. + +中间的: + profit += prices[peek - 1] - prices[start]; 听特别的。 + 当没有上涨趋势时候,peek-1也就是start, 所以这里刚好profit += 0. + +O(n) + + +--- +**19. [Best Time to Buy and Sell Stock III .java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20III%20.java)** Level: Medium + +比stock II 多了一个限制:只有2次卖出机会。也就是:找峰头;然后往下再找一个峰头。 + +怎么样在才能Optimize两次巅峰呢? + +从两边同时开始找Max!(棒棒的想法) + + leftProfit是从左往右,每个i点上的最大Profit。 + rightProfit是从i点开始到结尾,每个点上的最大profit. + 那么在i点上,就是leftProfit,和右边rightProfit的分割点。在i点,leftProfit+rightProfit相加,找最大值。 + +三个O(n),还是O(n) + + +--- +**20. [Best Time to Buy and Sell Stock IV.java](https://github.com/awangdev/LintCode/blob/master/Java/Best%20Time%20to%20Buy%20and%20Sell%20Stock%20IV.java)** Level: Hard + +记得要理解: 为什么 i-1天的卖了又买,可以和第 i 天的卖合成一次交易? + 因为每天交易的price是定的。所以卖了又买,等于没卖!这就是可以合并的原因。要对价格敏感啊少年。 + +Inspired from here: +http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html + +局部最优解 vs. 全局最优解: + local[i][j] = max(global[i – 1][j – 1] + diff, local[i – 1][j] + diff) + global[i][j] = max(global[i – 1][j], local[i][j]) + +local[i][j]: 第i天,当天一定进行第j次交易的profit +global[i][j]: 第i天,总共进行了j次交易的profit. + +local[i][j]和global[i][j]的区别是:local[i][j]意味着在第i天一定有交易(卖出)发生。 + 当第i天的价格高于第i-1天(即diff > 0)时,那么可以把这次交易(第i-1天买入第i天卖出)跟第i-1天的交易(卖出)合并为一次交易,即local[i][j]=local[i-1][j]+diff; + 当第i天的价格不高于第i-1天(即diff<=0)时,那么local[i][j]=global[i-1][j-1]+diff,而由于diff<=0,所以可写成local[i][j]=global[i-1][j-1]。 + (Note:在我下面这个solution里面没有省去 +diff) + +global[i][j]就是我们所求的前i天最多进行k次交易的最大收益,可分为两种情况: + 如果第i天没有交易(卖出),那么global[i][j]=global[i-1][j]; + 如果第i天有交易(卖出),那么global[i][j]=local[i][j]。 + + + + +--- +**21. [Binary Representation.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Representation.java)** Level: Hard + +首先要分两半解决,断点是'.': str.split("\\."); + +Integer那一半好弄,whie loop里: num%2, num/2。 + +Decimal那边复杂点. + bit == 1的数学条件:当下num * 2 >= 1。 更新: num = num * 2 - 1; + bit == 0的数学条件: num * 2 < 1. 更新: num = num * 2 + +注意:num是 double, 小数在 (num = num * 2 -1)的公式下可能无限循环. 因此check: num重复性,以及binary code < 32 bit. + +(所以题目也才有了32BIT的要求!) + + +--- +**22. [Binary Search Tree Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Search%20Tree%20Iterator.java)** Level: Hard + +用O(h)空间的做法: + +理解binary search tree inorder traversal的规律: + 先找left.left.left ....left 到底,这里是加进stack. + 然后考虑parent,然后再right. + +例如这题: + stack里面top,也就是tree最左下角的node先考虑,取名rst. + 其实这个rst拿出来以后, 它也同时是最底层left null的parent,算考虑过了最底层的parent。 + 最后就考虑最底层的parent.right, 也就是rst.right. + +注意: + next()其实有个while loop, 很可能是O(h).题目要求average O(1),所以也是okay的. + + +用O(1)空间的做法:不存stack, 时刻update current为最小值。 + +找下一个最小值,如果current有right child: + 和用stack时的iteration类似,那么再找一遍current.right的left-most child,就是最小值了。 + +如果current没有right child: + 那么就要找current node的右上parent, search in BinarySearchTree from root. + +注意: + 一定要确保找到的parent满足parent.left == current. + 反而言之,如果current是parent的 right child, 那么下一轮就会重新process parent。 + 但是有错:binary search tree里面parent是小于right child的,也就是在之前一步肯定visit过,如此便会死循环。 + + + +--- +**23. [Binary Tree Inorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Inorder%20Traversal.java)** Level: Easy + +法一: +Recursive: Divide and Conquer, with helper(dfs) method + +法二: +Stack: +Add left nodes all the way +Print curr +Move to right, add right if possible. + +注意stack.pop()在加完left-most child 的后,一定要curr = curr.right. + +若不右移,很可能发生窘境: +curr下一轮还是去找自己的left-most child,不断重复curr and curr.left, 会infinite loop, 永远在左边上下上下。 + + + +--- +**24. [Binary Tree Level Order Traversal II.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Level%20Order%20Traversal%20II.java)** Level: Medium + +普通BFS,用一个queue,加上一个queue.size()来交替换行. + +rst里面add(0,...)每次都add在list开头 + + + +--- +**25. [Binary Tree Level Order Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Level%20Order%20Traversal.java)** Level: Medium + +方法1. 最普通,Non-recursive: BFS, queue, 用个queue.size()来end for loop:换行。 + 或者用两个queue. 当常规queue empty,把backup queue贴上去。 + +方法2. Recursive with dfs: + 每个level都应该有个ArrayList. 那么用一个int level来查看:是否每一层都有了相应的ArrayList。 + 如果没有,就加上一层。 + 之后每次都通过DFS在相应的level上面加数字。 + + + +--- +**26. [Binary Tree Longest Consecutive Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Longest%20Consecutive%20Sequence.java)** Level: Medium + +屌炸天的4行代码。Divide and Conquer + +主要想法: +Recursive用好。首先在这个level比一比,可否成。 +不成的话,另立门户, count = 1。 +然后左右开弓。再把结果拿过来比较一下就好了。 + + +--- +**27. [Binary Tree Maximum Path Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Maximum%20Path%20Sum%20II.java)** Level: Medium + +比Binary Tree Maximum Path Sum I 简单许多. 因为条件给的更多:at least 1 node + have to start from root => have to have root. + +方法1: +维持一个global或者recursive里的sum。traversal entire tree via DFS. 简单明了。 + + +方法2: +Single path: either left or right. +If the path sum < 0, just skip it. + + +--- +**28. [Binary Tree Maximum Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Maximum%20Path%20Sum.java)** Level: Medium + +第一次做有点难理解,复杂原因是:因为可能有负值啊。不能乱assume正数。 + single path max 的计算是为了给后面的comboMax用的。 + 如果single path max小于0,那没有什么加到parent上面的意义,所以就被再次刷为0. + +combo的三种情况:(root可能小于0) + 1. 只有left + 2。 只有右边 + 3. root大于0,那么就left,right,curr全部加起来。 + +情况1和情况2取一个最大值,然后和情况三比较。做了两个Math.max(). 然后就有了这一层的comboMax + + +12.11.2015 recap: + So totally, 5 conditions: + (save in single) + left + curr.val OR right + curr.val + (save in combo:) + left, right, OR left + curr.val + right + + + + +--- +**29. [Binary Tree Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Path%20Sum.java)** Level: Easy + +Binary Tree的一个基本题。 +遍历到底,比较sum vs. target。 +注意divide的情况。要把遍历的例子写写。 + +LeetCode: Path Sum II + + +--- +**30. [Binary Tree Paths.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Paths.java)** Level: Easy + +方法1: +Recursive:分叉。Helper。 + +方法2,Iterative: + 非递归练习了一下 + 因为要每次切短list, 所以再加了一个Stack 来存level + + + +--- +**31. [Binary Tree Postorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Postorder%20Traversal.java)** Level: Easy + +最prefer 2 stack的做法: + stack1和stack2合作。倒水。记这个做法。。。挺神奇的。 + +Divide and Conquer 的recursive方法也非常明了! + +注意,这些binary tree traversal的题目,常常有多个做法:recursive or iterative + + +--- +**32. [Binary Tree Preorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Preorder%20Traversal.java)** Level: Easy + +Preorder 写写, stack +1. Divide and conquer +2. Stack(NON-recursive) push curr, push right, push left. +3. recursive with helper method + + +--- +**33. [Binary Tree Right Side View.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Right%20Side%20View.java)** Level: Medium + +最右:即level traversal每一行的最末尾. + +BFS,用queue.size()来出发saving result. + + +--- +**34. [Binary Tree Serialization.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Serialization.java)** Level: Medium + +方法1: BFS. Non-recursive, using queue. 想法直观。level-order traversal. save到一个string里面就好。 + +方法2: DFS. Recursive. 需要一点思考。basically divide and conquer. 但是代码相对来说短。 + + +--- +**35. [Binary Tree Zigzag Level Order Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Binary%20Tree%20Zigzag%20Level%20Order%20Traversal.java)** Level: Medium + +简单的level traversal.根据level奇数偶数而add到不同位子. + + +--- +**36. [Building Outline.java](https://github.com/awangdev/LintCode/blob/master/Java/Building%20Outline.java)** Level: Hard + +又叫做skyline + +看网上的解答做, 思路很漂亮。 (http://codechen.blogspot.com/2015/06/leetcode-skyline-problem.html?_sm_au_=isVmHvFmFs40TWRt) + +跟scan line的approach类似: +1. 把所有点分出来, 每个点有index x, 再加上一个height. +2. 在这个list上排序,根据index和height(注意用负数标记building start point,这样保证start在end 之前。). 叫做 heightPoints +3. 在processs时候用max-heap (reversed priorityqueue),在ieteraete heightPoints 来存最大的height . 遇到peek,就是一个合理的解 + 处理1:因为start,end的height都存在了heightPoints里面,这里就是用来check end of bulding的,然后把height 从queue里面remove. + 处理2:重复x 上面的许多height? priorityqueue给了我们最高,这okay了;那么其他的重复点,用一个int prev来mark之前做过的,一旦重复,跳过。 + +想法非常natural。 大题目,脑子乱。 +看了解答再去想,挺naturally doable的。 + + +--- +**37. [Burst Balloons.java](https://github.com/awangdev/LintCode/blob/master/Java/Burst%20Balloons.java)** +dp[i][j] = balloons i~j 之间的sum. 然后找哪个点开始burst? 设为x。 +For loop 所有的点作为x, 去burst。 +每次burst都切成了三份:左边可以recusive 求左边剩下的部分的最大值 + 中间3项相乘 + 右边递归下去求最大值。 + + +这个是momorization, 而不纯是DP +因为recursive了,其实还是搜索,但是memorize了求过的值,节省了Processing + +--- +**38. [Change to Anagram.java](https://github.com/awangdev/LintCode/blob/master/Java/Change%20to%20Anagram.java)** Level: Easy + +简单的check int[26] 26个小写字母是否需要改变。若需要count+1. + +主要HackerRank里要注意自己写: Scanner, import java.util, non-static method ...etc. + +注意: 最后count出来要除以2:字母不同,会在不同的字母位上加减count,那么就是刚好重复计算了一遍。所以除以二。 + + +--- +**39. [Classical Binary Search.java](https://github.com/awangdev/LintCode/blob/master/Java/Classical%20Binary%20Search.java)** Level: Easy + + while: start + 1 < end + mid = start + (end - start) / 2; + 末尾double check start, end. + + + +--- +**40. [Climbing Stairs.java](https://github.com/awangdev/LintCode/blob/master/Java/Climbing%20Stairs.java)** Level: Easy + +方法1: DP。爬坡到i点总共有的方法,取决于i-1点和i-2的情况。也就是DP(i-1) + DP(i-2). + +还可以用滚动数组优化一点:因为用到的变量就只有i,i-1,i-2,可以被替代。 + 注意要写好‘滚动’的代码。 + +方法2: DFS但是timeout + + +--- +**41. [Clone Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Clone%20Graph.java)** Level: Medium + +Use HashMap to mark cloned nodes. + +先能复制多少Node复制多少。然后把neighbor 加上 + + + +--- +**42. [Closest Binary Search Tree Value.java](https://github.com/awangdev/LintCode/blob/master/Java/Closest%20Binary%20Search%20Tree%20Value.java)** Level: Easy + +Binary Search. 记录找到过的closest. 直到tree leaf, 找完return + + +--- +**43. [Closest Number in Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Closest%20Number%20in%20Sorted%20Array.java)** Level: Easy + +跟Closest Binary Search Tree Vlaue类似: + +Binary search. 考虑mid-1, mid+1. +一旦没有mid = target.index。 那么target最终就narrow down在(mid-1,mid) 或者(mid,mid+1) + +--- +**44. [Coins in a Line.java](https://github.com/awangdev/LintCode/blob/master/Java/Coins%20in%20a%20Line.java)** +However, 分析过后简直屌炸天。一个 n%3就解决了。纯粹math. + +--- +**45. [ColorGrid.java](https://github.com/awangdev/LintCode/blob/master/Java/ColorGrid.java)** Level: Medium + +用HashMap, 理解题目规律,因为重复的计算可以被覆盖,所以是个优化题。 + +消灭重合点: +如果process当下col, 其实要减去过去所有加过的row的交接点。。。 +再分析,就是每次碰到row 取一个单点, sumRow += xxx。 +然后process当下col时候, sum += colValue * N - sumRow. 就等于把交叉所有row(曾经Process过的row)的点减去了。很方便。 + +最后read in 是O(P), process也是O(P). + + + +--- +**46. [Combination Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Combination%20Sum%20II.java)** Level: Medium + +还是DFS. 和Combination Sum I 类似. +确保Helper是用i+1,下一层的数字, 不允许重复。 + + +--- +**47. [Combination Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Combination%20Sum.java)** Level: Medium + +递归,backtracking. 非常normal。需要先sort. +记得求sum时候也pass 一个sum进去,backtracking一下sum也,这样就不必每次都sum the list了。 + +题目里面所同一个元素可以用n次,但是,同一种solution不能重复出现。如何handle? + +1. 用一个index (我们这里用了start)来mark每次recursive的起始点。 +2. 每个recursive都从for loop里面的i开始,而i = start。 也就是,下一个iteration,这个数字会有机会被重复使用。 +3. 同时,确定在同一个for loop里面,不同的Index上面相同的数字,不Process两遍。用一个prev 作为checker. + +假如[x1, x2, y, z], where x1 == x2, 上面做法的效果: +我们可能有这样的结果: x1,x1,x1,y,z +但是不会有:x1,x2,x2,y,z +两个solution从数字上是一样的,也就是duplicated solution, 要杜绝第二种。 + + +--- +**48. [Combinations.java](https://github.com/awangdev/LintCode/blob/master/Java/Combinations.java)** Level: Medium + +Combination DFS。 画个图想想. 每次从1~n里面pick一个数字i + +因为下一层不能重新回去 [0~i]选,所以下一层recursive要从i+1开始选。 + + +--- +**49. [Compare Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Compare%20Strings.java)** Level: Easy + +比较一下大小, null. + +然后用char[]来count chars from A. 再对照chars in B. + + +--- +**50. [Complete Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Complete%20Binary%20Tree.java)** Level: Easy + +BFS + +Use a flag . 当出现了第一次有 null children的node的时候, +说明complete tree的最低level出现了。 +自此以后,queue再不该有node再有child, queue后面出现的node的左右孩子应该都是null. + + + +--- +**51. [Construct Binary Tree from Inorder and Postorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Construct%20Binary%20Tree%20from%20Inorder%20and%20Postorder%20Traversal.java)** Level: Medium + +写个Inorder和Postorder的例子。利用他们分left/right subtree的规律解题。 + +Postorder array 的末尾, 就是当下层的root. +在Inorder array 里面找到这个root,就刚好把左右两边分割成left/right tree。 + +这题比较tricky地用了一个helper做recursive。 特别要注意处理index的变化, precisely考虑开头结尾 + +可惜有个不可避免的O(n) find element in array. + + +--- +**52. [Construct Binary Tree from Inorder and Preorder Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Construct%20Binary%20Tree%20from%20Inorder%20and%20Preorder%20Traversal.java)** Level: Medium + +和Construct from Inorder && Postorder 想法一样。 + +写出Preorder和Inorder的字母例子,发现Preorder的开头总是这Level的root。依此写helper,注意处理index。 + + +--- +**53. [Container With Most Water.java](https://github.com/awangdev/LintCode/blob/master/Java/Container%20With%20Most%20Water.java)** +左右两墙,往中间跑动。 +另,若一面墙已经小于另外一面,就要移动,换掉矮墙(可能下一面更高,或更低);但决不能换掉当下的高墙,因为低墙已经limit的盛水的上限,若高墙移动,导致两墙之间距离减少,就注定水量更少了。(弄啥来,不能缺心眼啊) + +--- +**54. [Convert Binary Search Tree to Doubly Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Binary%20Search%20Tree%20to%20Doubly%20Linked%20List.java)** Level: Medium + +会iterative traverse Binary Search Tree就好(Stack && handle left-dig-down), 然后create Doubly-ListNode 时候注意就好. + +注意inorder traversal在check right node的事后, +不论right == null or != null, 每次都要强行move to right. + +如果不node = node.right, +很可能发生窘境: +node alays = stack.top(), 然后stack.top()一直是一开始把left 全部遍历的内容。所以就会infinite loop, 永远在左边上下上下。 + + +--- +**55. [Convert Expression to Polish Notation.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Expression%20to%20Polish%20Notation.java)** Level: Hard + +还是Expression Tree (Min-Tree). + +根据题意,Tree出来以后,来个Pre-order-traversal. + +Note: label需要是String.虽然 Operator是长度为1的char, 但是数字可为多位。 + + +--- +**56. [Convert Expression to Reverse Polish Notation.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Expression%20to%20Reverse%20Polish%20Notation.java)** Level: Hard + +build expression tree。 + +这个里面把TreeNode就当做成我们需要的node,里面扩展成有left/right child的node. + +建造Expression Tree,然后根据 Reverse Polish Notation 的定义,来个post-traversal就行了。 + + +--- +**57. [Convert Integer A to Integer B.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Integer%20A%20to%20Integer%20B.java)** Level: Easy + +Bit Manipulation + +a^b 显示出bit format里面有不同binary code的数位. + +每次 (a^b)>>i 移动i位之后, 再 & 1时其实是指留下这一位的数字. + +count it up + + +--- +**58. [Convert Sorted Array to Binary Search Tree With Minimal Height.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Sorted%20Array%20to%20Binary%20Search%20Tree%20With%20Minimal%20Height.java)** Level: Easy + +Binary Search的感觉. 中间一开两半, divde and conquer,左右各自recursive下去build left/right child. + + +--- +**59. [Convert Sorted List to Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Convert%20Sorted%20List%20to%20Binary%20Search%20Tree.java)** Level: Medium + +Divide and Conquer +用快慢pointer + +找到mid。 +然后把root = mid.next + +然后开始sortedListToBST(mid.next.next); //后半段 +mid.next = null;//非常重要,要把后面拍过序的断掉 +sortedListToBST(head); //从头开始的前半段 + + +最后root.left, root.right merge一下。 + + +--- +**60. [Copy List with Random Pointer.java](https://github.com/awangdev/LintCode/blob/master/Java/Copy%20List%20with%20Random%20Pointer.java)** Level: Medium + +Basic Implementation, 其中用了一下HashMap: + +遍历head.next .... null. +每一步都check map里面有没有head。没有?加上。 +每一步都check map里面有没有head.random。没有?加上。 + + +--- +**61. [Cosine Similarity.java](https://github.com/awangdev/LintCode/blob/master/Java/Cosine%20Similarity.java)** Level: Easy + +basic implementation + + +--- +**62. [Count 1 in Binary.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%201%20in%20Binary.java)** Level: Easy + +1. 可以把integer -> string -> char array. + +2. 或者就 count += num << i & 1 + + +--- +**63. [Count and Say.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20and%20Say.java)** Level: Easy + +Basic implementation. Count duplicates and print + + +--- +**64. [Count of Smaller Number before itself.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20of%20Smaller%20Number%20before%20itself.java)** Level: Hard + +与Count of Smaller Number非常类似。以实际的value来构成segment tree,leaf上存(count of smaller number)。 + +Trick: 先Query,再modify. +每次Query时候,A[i]都还没有加入到Segment Tree 里面,而A[i+1,...etc]自然也还没有加进去。 +那么就自然是coutning smaller number before itself. +刁钻啊! + +另外注意: +在modify里面:多Check了root.start <= index 和 index <= root.end。 过去都忽略了。以后可以把这个也写上。 +(其实是Make sense的,就是更加严格地check了index再 root.left 或者 root.right里面的站位) + + +--- +**65. [Count of Smaller Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20of%20Smaller%20Number.java)** Level: Medium + +和平时的segment tree问题不同。 0 ~ n-1代表实际数字。是造一个based on real value的segment tree. +Modify时,把array里面的value带进去,找到特定的位子(leaf),然后count+1. + +最终在SegmentTree leaf上面全是array里面实际的数字。 + +trick: +在query前,给进去的start和end是: 0 ~ value-1. +value-1就是说,找比自己所在range小1的range(那么自然而然地就不包括自己了),这样就找到了smaller number. + + +[那么其他做过的SegmentTree是怎么样呢?] +那些构成好的SegmentTree(找min,max,sum)也有一个Array。但是构成Tree时候,随Array的index而构架。 +也就是说,假如有Array[x,y,....]:在leaf,会有[0,0] with value = x. [1,1] with value = y. + +[但是这题] +构成时,是用actual value.也就是比如Array[x,y,....]会产生leaf:[x,x]with value = ..; [y,y]with value =... + +其实很容易看穿: +若给出一个固定的array构成 SegmentTree,那估计很简单:按照index从0~array.lengh,leaf上就是[0,0] with value = x. + +若题目让构造一个空心SegmentTree, based on value 0 ~ n-1 (n <= 10000), 然后把一个Array的value modify 进去。 +这样八成是另外一种咯。 + + +--- +**66. [Count Primes.java](https://github.com/awangdev/LintCode/blob/master/Java/Count%20Primes.java)** Level: Easy + +什么是prime number: >=2的没有除自己和1以外公约数的数。 + +还有另外一个定义方法!! +这个n,有没有小于n的一个i,而达到: i*i + # of i = n. 如果有,那就不是 prime。 + +方法很牛逼也很数学。没做的时候可能想不到。做了之后就觉得,哎,我去,有道理啊。 +简而言之:简历一个boolean长条,存isPrime[]。 然后从i=2, 全部变true. +然后利用这个因子的性质,非prime满足条件: self*self, self * self + self ... etc. +所以就check每一个j, j+i, j+i+i, 然后把所有non-prime全部mark成false. +最后,数一遍还剩下的true个数就好了 + + +--- +**67. [Course Schedule II.java](https://github.com/awangdev/LintCode/blob/master/Java/Course%20Schedule%20II.java)** Level: Medium + +详细的中文分析,看Course Schedule I + + +--- +**68. [Course Schedule.java](https://github.com/awangdev/LintCode/blob/master/Java/Course%20Schedule.java)** Level: Medium + +有点绕,但是做过一次就明白一点。 +是topological sort的题目。一般都是给有dependency的东西排序。 + +最终都会到一个sink node, 再不会有向后的dependency, 在那个点截止。 +我就已这样子的点为map的key, 然后value是以这个node为prerequisite的 list of courses. + +画个图的话,prerequisite都是指向那个sink node, 然后我们在组成map的时候,都是从sink node 发散回来到dependent nodes. + +在DFS里面,我们是反向的, 然后,最先完全visited的那个node, 肯定是最左边的node了,它被mark的seq也是最高的。 + +而我们的sink node,当它所有的支线都visit完了,seq肯定都已经减到最小了,也就是0,它就是第一个被visit的。 + + +最终结果: +每个有pre-requisit的node都trace上去(自底向上),并且都没有发现cycle.也就说明schedule可以用了。 + + +--- +**69. [Data Stream Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Data%20Stream%20Median.java)** Level: Hard + +把Input stream想成向上的山坡。山坡中间那点,自然就是median. + +前半段,作为maxHeap,关注点是PriorityQueue的峰点,也就是实际上的median. + +后半段,作为minHeap,正常的PriorityQueue。 开头是最小的。 + +Note:题目定义meadian = A[(n-1)/2],也就是说maxHeap需要和minHeap长度相等,或者多一个element,最后可以直接poll() and return. + + +--- +**70. [Delete Digits.java](https://github.com/awangdev/LintCode/blob/master/Java/Delete%20Digits.java)** Level: Medium + +数位靠前的,权值更大. 所以硬来把靠前的相对更大的(跟following digit相比)去掉。 + + +--- +**71. [Delete Node in the Middle of Singly Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Delete%20Node%20in%20the%20Middle%20of%20Singly%20Linked%20List.java)** Level: Easy + +Just do it. Link curr.next to curr.next.next + + +--- +**72. [Distinct Subsequences.java](https://github.com/awangdev/LintCode/blob/master/Java/Distinct%20Subsequences.java)** Level: Hard + +Not Done + + +--- +**73. [Edit Distance.java](https://github.com/awangdev/LintCode/blob/master/Java/Edit%20Distance.java)** Level: Medium + +Not Done + + +--- +**74. [Encode and Decode Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Encode%20and%20Decode%20Strings.java)** Level: Medium + +方法1: +用数字+"#"+string来encode. +基于我们自己定的规律, 在decode的里面不需要过多地去check error input, assume所有input都是规范的. +decode就是找"#",然后用"#"前的数字截取后面的string. + + + +Old Solution: +Cast character into int. 串联起来, seperate by "LINE". +handle empty list [], or just null: 要把Null特别mark一下为‘NULL’, 这样decode时才能check到。 adminadmin + + + +--- +**75. [ExcelSheetColumnNumber .java](https://github.com/awangdev/LintCode/blob/master/Java/ExcelSheetColumnNumber%20.java)** Level: Easy + +'A' - 'A' = 0. 所以 char - 'A' + 1 = 题目里的对应数位。 +26位运算和10位一样嘛,num += 每位的digit * Math.pow(26, 数位号)。 + + + +--- +**76. [Expression Evaluation.java](https://github.com/awangdev/LintCode/blob/master/Java/Expression%20Evaluation.java)** Level: Hard + +Build Expression Tree的另外一个变形,依然Min Tree. + +build好Min Tree以后,做PostTraversal. Divde and Conquer: +先recursively找到 left和right的大小, 然后evaluate中间的符号。 + +Note: +1. Handle数字时,若left&&right Child全Null,那必定是我们weight最大的数字node了。 +2. 若有个child是null,那就return另外一个node。 +3. prevent Integer overflow during operation:过程中用个Long,最后结局在cast back to int. + + +--- +**77. [Expression Tree Build.java](https://github.com/awangdev/LintCode/blob/master/Java/Expression%20Tree%20Build.java)** Level: Hard + +和Max-tree一样,感谢http://blog.welkinlan.com/2015/06/29/max-tree-lintcode-java/ + +这个题目是Min-tree, 头上最小,Logic 和max-tree如出一辙 + +注意treeNode,为了帮助ExpressionTreeNode 排序。它加了一个weight based on expression,协助build Min-Tree 排序。 + +Space: O(n) +Time on average: O(n). + + +--- +**78. [Fast Power.java](https://github.com/awangdev/LintCode/blob/master/Java/Fast%20Power.java)** Level: Medium + +a^n可以被拆解成(a*a*a*a....*a), 是乘机形式,而%是可以把每一项都mod一下的。所以就拆开来take mod. + +这里用个二分的方法,recursively二分下去,直到n/2为0或者1,然后分别对待. + +注意1: 二分后要conquer,乘积可能大于Integer.MAX_VALUE, 所以用个long. + +注意2: 要处理n%2==1的情况,二分时候自动省掉了一份,要乘一下。 + + + +--- +**79. [Fibonacci.java](https://github.com/awangdev/LintCode/blob/master/Java/Fibonacci.java)** Level: Easy + +方法1: DP array. + +方法1.1: 滚动数组, 简化DP。 + +方法2: recursively calculate fib(n - 1) + fib(n - 2). 公式没问题, 但是时间太长, timeout. + + + +--- +**80. [Find Minimum in Rotated Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Minimum%20in%20Rotated%20Sorted%20Array%20II.java)** +Medium Find Minimum in Rotated Sorted Array II My Submissions + +40% Accepted +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +Find the minimum element. + +The array may contain duplicates. + +Example +Given [4,4,5,6,7,0,1,2] return 0 + +Tags Expand +Binary Search Divide and Conqueri + +Thinking process: +It seems using binary search will leads to O(n), so just use a for loop with O(n) +*/ + +public class Solution { + /** + * @param num: a rotated sorted array + * @return: the minimum number in the array + */ + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return -1; + } + int min = Integer.MAX_VALUE; + for (int i = 0; i < num.length; i++) { + if (min > num[i]) { + min = num[i]; + } + } + return min; + } +} + + +--- +**81. [Find Minimum in Rotated Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Minimum%20in%20Rotated%20Sorted%20Array.java)** +Suppose a sorted array is rotated at some pivot unknown to you beforehand. + +(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). + +Find the minimum element. + +You may assume no duplicate exists in the array. + +Example +Given [4,5,6,7,0,1,2] return 0 + +Tags Expand +Binary Search + +Thinking process: +Understand how to use binary in this problem: compare the mid point with end point. +In this problem, because the sorted line is cut at one point then rotate, so one of the line is absolutely greater than the other line. +Situation 1: +if mid < end : that means minimum is on the end point's line. Move end to left. end = mid. +Situation 2: +if mid > end: that means there must be a mountain-jump somewhere after mid and before end, which is the minimum point. Now move start to mid. +*/ + +public class Solution { + /** + * @param num: a rotated sorted array + * @return: the minimum number in the array + */ + public int findMin(int[] num) { + if (num == null || num.length == 0) { + return -1; + } + int start = 0; + int end = num.length - 1; + int mid = 0; + while (start + 1 < end) { + mid = start + (end - start) / 2; + if (num[mid] > num[end]) { + start = mid; + } else { + end = mid; + } + } + if (num[start] < num[end]) { + return num[start]; + } else { + return num[end]; + } + } +} + + +--- +**82. [Find Peak Element II.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Peak%20Element%20II.java)** +There is an integer matrix which has the following features: + +The numbers in adjacent positions are different. +The matrix has n rows and m columns. +For all i < m, A[0][i] < A[1][i] && A[n - 2][i] > A[n - 1][i]. +For all j < n, A[j][0] < A[j][1] && A[j][m - 2] > A[j][m - 1]. +We define a position P is a peek if: + +A[j][i] > A[j+1][i] && A[j][i] > A[j-1][i] && A[j][i] > A[j][i+1] && A[j][i] > A[j][i-1] +Find a peak element in this matrix. Return the index of the peak. + +Have you met this question in a real interview? Yes +Example +Given a matrix: + +[ + [1 ,2 ,3 ,6 ,5], + [16,41,23,22,6], + [15,17,24,21,7], + [14,18,19,20,10], + [13,14,11,10,9] +] +return index of 41 (which is [1,1]) or index of 24 (which is [2,2]) + +Note +The matrix may contains multiple peeks, find any of them. + +Challenge +Solve it in O(n+m) time. + +If you come up with an algorithm that you thought it is O(n log m) or O(m log n), can you prove it is actually O(n+m) or propose a similar but O(n+m) algorithm? + +Tags Expand +Binary Search LintCode Copyright Matrix +*/ + +/* + NOT DONE. Will try if have time +*/ + + +class Solution { + /** + * @param A: An integer matrix + * @return: The index of the peak + */ + public List findPeakII(int[][] A) { + // write your code here + } +} + + +--- +**83. [Find Peak Element.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20Peak%20Element.java)** +一个特别的check condition, 和特别的move left, move right的case罢了。 + +--- +**84. [Find the Connected Component in the Undirected Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20the%20Connected%20Component%20in%20the%20Undirected%20Graph.java)** Level: Medium + +BFS遍历,把每个node的neighbor都加进来。 + +一定注意要把visit过的node Mark一下。因为curr node也会是别人的neighbor,会无限循环。 + +Component的定义:所有Component内的node必须被串联起来via path (反正这里是undirected, 只要链接上就好) + +这道题:其实component在input里面都已经给好了,所有能一口气visit到的,全部加进queue里面,他们就是一个component里面的了。 + +而我们这里不需要判断他们是不是Component。 + + +--- +**85. [Find the Weak Connected Component in the Directed Graph.java](https://github.com/awangdev/LintCode/blob/master/Java/Find%20the%20Weak%20Connected%20Component%20in%20the%20Directed%20Graph.java)** Level: Medium + +Identify这是个union-find问题还挺巧妙。 +看到了weak component的形式: 一个点指向所有,那么所有的点都有一个公共的parent,然后就是要找出这些点。 + +为何不能从一个点出发,比如A,直接print它所有的neighbors呢? + 不行,如果轮到了B点,那因为是directed,它也不知道A的情况,也不知道改如何继续加,或者下手。 + +所以,要把所有跟A有关系的点,或者接下去和A的neighbor有关系的点,都放进union-find里面,让这些点有Common parents. + +最后output的想法: +做一个 map 。 +之前我们不是给每个num都存好了parent了嘛。 +每个num都有个parent, 然后不同的parent就创造一个不同的list。 +最后,把Map里面所有的list拿出来就好了。 + + +--- +**86. [First Bad Version.java](https://github.com/awangdev/LintCode/blob/master/Java/First%20Bad%20Version.java)** Level: Medium + +Binary Search + +根据isBadVersion的性质,判断还如何end=mid or start=mid. +isBadVersion 是有方向的嘛,一个点错了,后面全错。 + + +--- +**87. [First Missing Positive.java](https://github.com/awangdev/LintCode/blob/master/Java/First%20Missing%20Positive.java)** +Given an unsorted integer array, find the first missing positive integer. + +Example +Given [1,2,0] return 3, and [3,4,-1,1] return 2. + +Challenge +Your algorithm should run in O(n) time and uses constant space. + +Tags Expand +Array + +Thoughts: +It means: after it's sorted, what's the first missing postive int counted from 1 ---> more + +1. Arrays.sort(); +2. count = first non-zero element in A. +3. count +1, and see if maches the current A[i]? + +NOTE: +Deal with negative and positive number separately +Watch out for redundant number: ask if the list has duplicated elements +*/ + + +public class Solution { + /** + * @param A: an array of integers + * @return: an integer + */ + public int firstMissingPositive(int[] A) { + if (A == null || A.length == 0) { + return 1; + } + Arrays.sort(A); + int count = -1; + for (int i = 0; i < A.length; i++) { + if (A[i] > 0) { + if (count < 0) {//process 1st positive element + count = A[i]; + if (count != 1) { + return 1; + } + } + else if (A[i] == A[i - 1]) {//watch out for duplicates + count--; + } + else if(A[i] != count) {//if not match, kick out + return count; + } + count++; + } + } + if (count < 0) {//if all negative, return 1 + return 1; + } + return count; + } +} + +--- +**88. [Flatten 2D Vector.java](https://github.com/awangdev/LintCode/blob/master/Java/Flatten%202D%20Vector.java)** +Implement an iterator to flatten a 2d vector. + +For example, +Given 2d vector = + +[ + [1,2], + [3], + [4,5,6] +] +By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6]. + +Hint: + +How many variables do you need to keep track? +Two variables is all you need. Try with x and y. +Beware of empty rows. It could be the first few rows. +To write correct code, think about the invariant to maintain. What is it? +The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it? +Not sure? Think about how you would implement hasNext(). Which is more complex? +Common logic in two different places should be refactored into a common method. + + +Tags: Design +Similar Problems: (M) Binary Search Tree Iterator, (M) Zigzag Iterator, (M) Peeking Iterator + +*/ + +/* +Thoughts: +As hint indicates: use 2 pointers to hold position. +Use hasNext to validate (x,y) and move x. +Use next() to return (x,y) and move it(regardless of correctness, which is determined by hasNext()) +*/ +public class Vector2D { + private int x; + private int y; + private List> list; + public Vector2D(List> vec2d) { + if (vec2d == null) { + return; + } + this.x = 0; + this.y = 0; + this.list = vec2d; + } + + public int next() { + int rst = list.get(x).get(y); + if (y + 1 >= list.get(x).size()) { + y = 0; + x++; + } else { + y++; + } + return rst; + } + + public boolean hasNext() { + if (list == null) { + return false; + } + while (x < list.size() && list.get(x).size() == 0) { + x++; + y = 0; + } + if (x >= list.size()) { + return false; + } + if (y >= list.get(x).size()) { + return false; + } + return true; + } +} + +/** + * Your Vector2D object will be instantiated and called as such: + * Vector2D i = new Vector2D(vec2d); + * while (i.hasNext()) v[f()] = i.next(); + */ + +--- +**89. [Flatten Binary Tree to Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Flatten%20Binary%20Tree%20to%20Linked%20List.java)** Level: Easy + +Not Done + + + +--- +**90. [Flattern 2D Vector.java](https://github.com/awangdev/LintCode/blob/master/Java/Flattern%202D%20Vector.java)** +注意啊,一开始理解题意搞错:我以为是必须要排序正确,所以上来就PriorityQueue+HashMap搞得无比复杂。其实,这个跟一个nxn的matrix遍历,是没区别的拉。 +所有来个x,y,把2d list跑一变。 + + +--- +**91. [Flip Game II.java](https://github.com/awangdev/LintCode/blob/master/Java/Flip%20Game%20II.java)** +注意:不要乱改input s. recursive call 需要用原始的input s. + +这个题目李特是屌炸天的。 +我飞了九牛二虎之力(路子对),但是代码写的七荤八素,好长好长好长好长的。 +结果正解,三四行就搞定了。真是心有不甘啊。 +想法如下: +保证p1能胜利,就必须保持所有p2的move都不能赢。 +同时,p1只要在可走的Move里面,有一个move可以赢就足够了。 +(题目里面用一个for loop + 只要 满足条件就return true来表达 OR的意思:p1不同的路子,赢一种就行了) +p1: player1 +p2: player2 + + +--- +**92. [Flip Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Flip%20Game.java)** +很郁闷的就是条件不明,原来只需要从'++'转到'--'的情况,反过来没必要关注...搞了我半天啊 + +--- +**93. [Fraction to Recurring Decimal.java](https://github.com/awangdev/LintCode/blob/master/Java/Fraction%20to%20Recurring%20Decimal.java)** +很容易忽略的是integer的益处。 + +--- +**94. [Game of Life.java](https://github.com/awangdev/LintCode/blob/master/Java/Game%20of%20Life.java)** +According to the Wikipedia's article: +"The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970." + +Given a board with m by n cells, each cell has an initial state live (1) or dead (0). +Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules +(taken from the above Wikipedia article): + +Any live cell with fewer than two live neighbors dies, as if caused by under-population. +Any live cell with two or three live neighbors lives on to the next generation. +Any live cell with more than three live neighbors dies, as if by over-population.. +Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction. +Write a function to compute the next state (after one update) of the board given its current state. + +Follow up: +Could you solve it in-place? Remember that the board needs to be updated at the same time: +You cannot update some cells first and then use their updated values to update other cells. +In this question, we represent the board using a 2D array. + In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. + How would you address these problems? +Credits: +Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. + +Hide Company Tags Google TinyCo +Hide Tags Array +Hide Similar Problems (M) Set Matrix Zeroes + +*/ + +/* + Thoughts: + https://segmentfault.com/a/1190000003819277 + http://my.oschina.net/Tsybius2014/blog/514447 + build state machine. + take mod of 2 at the end. +*/ + +public class Solution { + public void gameOfLife(int[][] board) { + + } +} + +--- +**95. [Gas Station.java](https://github.com/awangdev/LintCode/blob/master/Java/Gas%20Station.java)** +There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. + +You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations. + +Return the starting gas station's index if you can travel around the circuit once, otherwise return -1. + +Example +Given 4 gas stations with gas[i]=[1,1,3,1], and the cost[i]=[2,2,1,1]. The starting gas station's index is 2. + +Note +The solution is guaranteed to be unique. + +Challenge +O(n) time and O(1) extra space + +Tags Expand +Greedy + +Thoughts: +Loop through the gas station, and track the possible starting index. +Start from i = 0 ~ gas.length, and use a second pointer move to track how far we are travelling + calculate: remain += gas[i] - cost[i]. (remain + gas[i] - cost[i]: the remaining gas plus i's gas, can we make it to i+1 gas station?) + if remain < 0, fail. Note: if from i ~ j can't work, even it's possible that i can make it to i+1's station, but i+1 ~ j won't work still. + Thus, once i's station failed to get to x, set index = x + 1: we are moving on to next possible starting point. + +'total':simply indicates if we can make it a circle +*/ + +public class Solution { + /** + * @param gas: an array of integers + * @param cost: an array of integers + * @return: an integer + */ + public int canCompleteCircuit(int[] gas, int[] cost) { + if (gas == null || cost == null || gas.length == 0 || cost.length == 0) { + return -1; + } + int start = 0; + int remain = 0; + int total = 0; + for (int i = 0; i < gas.length; i++) { + remain += gas[i] - cost[i]; + if (remain < 0) { + remain = 0; + start = i + 1; + } + total += gas[i] - cost[i]; + } + if (total < 0) { + return -1; + } + return start; + } +} + +--- +**96. [Generate Parentheses.java](https://github.com/awangdev/LintCode/blob/master/Java/Generate%20Parentheses.java)** +看thought.取或者不取(, ) + +--- +**97. [Graph Valid Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Graph%20Valid%20Tree.java)** Level: Medium + +复习Union-Find的另外一个种形式。 +题目类型:查找2个元素是不是在一个set里面。如果不在,false. 如果在,那就合并成一个set,共享parent. +存储的关键都是:元素相对的index上存着他的root parent. + +另一个union-find, 用hashmap的:http://www.lintcode.com/en/problem/find-the-weak-connected-component-in-the-directed-graph/ + + + +--- +**98. [Gray Code.java](https://github.com/awangdev/LintCode/blob/master/Java/Gray%20Code.java)** Level: Medium + +题目蛋疼,目前只接受一种结果。 + +BackTracking + DFS: + Recursive helper里每次flip一个 自己/左边/右边. Flip过后还要恢复原样.遍历所有. + +曾用法(未仔细验证): +基本想法就是从一个点开始往一个方向走,每次flip一个bit, 碰壁的时候就回头走。 + + +--- +**99. [Group Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Group%20Anagrams.java)** Level: Medium + +方法一: 60% + +和check anagram 想法一样:转化并sort char array,用来作为key。 + +把所有anagram 存在一起。注意结尾Collections.sort(). + +O(NKlog(K)), N = string[] length, k = longest word length + + +优化:80% ~ 97% + +用固定长度的char[26] arr 存每个字母的frequency; 然后再 new string(arr). +因为每个位子上的frequency的变化,就能构建一个unique的string + + +错误的示范: 尝试先sort input strs[],但是NlogN 其实效率更低. 13% + + + +--- +**100. [Group Shifted Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Group%20Shifted%20Strings.java)** Level: Easy + +相同shift规则的string, 能被推算到同一个零起始点,就是共同减去一个char,最后就相等。以此作为key,用HashMap。一目了然。 + +记得根据题目意思,一开始要String[] sort一下。 + + +--- +**101. [H-Index II.java](https://github.com/awangdev/LintCode/blob/master/Java/H-Index%20II.java)** +binary search + +--- +**102. [H-Index.java](https://github.com/awangdev/LintCode/blob/master/Java/H-Index.java)** + 当然,搜索一遍时候可以优化,用binary search. 但是没意义,因为array.sort已经用了nlogn + +o(n)也可以,用bucket. 比较巧妙。 + + + +--- +**103. [Happy Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Happy%20Number.java)** Level: Easy + +Basic Implementation of the requirements. + +用HashSet存查看过的数值。若重复,return false. + + +--- +**104. [Hash Function.java](https://github.com/awangdev/LintCode/blob/master/Java/Hash%20Function.java)** Level: Easy + +解释Hash怎么道理。Hash function例子: +hashcode("abcd") = (ascii(a) * 33^3 + ascii(b) * 33^2 + ascii(c) *33^1 + ascii(d)*33^0) % HASH_SIZE + +用到的参数比如: magic number 33, HASH_SIZE. + +Hash的用法是:给一个string key, 转换成数字,从而把size变得更小。 +真实的implementation还要处理collision, 可能需要design hash function 等等。 + + +每一步都: +hashRst = hashRst * 33 + (int)(key[i]); +hashRst = hashRst % HASH_SIZE; +原因是,hashRst会变得太大,所以不能算完再%... + + +--- +**105. [HashHeap.java](https://github.com/awangdev/LintCode/blob/master/Java/HashHeap.java)** Level: Hard + +非题.是从九章找来的HashHeap implementation. + + +--- +**106. [HashWithArray.java](https://github.com/awangdev/LintCode/blob/master/Java/HashWithArray.java)** Level: Easy + + + +--- +**107. [HashWithCustomizedClass(LinkedList).java](https://github.com/awangdev/LintCode/blob/master/Java/HashWithCustomizedClass(LinkedList).java)** Level: Medium + +练习HashMap with customized class. + + +--- +**108. [Heapify.java](https://github.com/awangdev/LintCode/blob/master/Java/Heapify.java)** Level: Medium + +Heap用的不多. 得用一下, 才好理解。 +通常default 的PriorityQueue就是给了一个现成的min-heap:所有后面的对应element都比curr element 小。 + +Heapify里面的siftdown的部分: + 只能从for(i = n/2-1 ~ 0), 而不能从for(i = 0 ~ n/2 -1): 必须中间开花,向上跑的时候才能确保脚下是符合heap规则的 + +Heapify/SiftDown做了什么? +确保在heap datastructure里面curr node下面的两个孩子,以及下面所有的node都遵循一个规律。 +比如在这里,若是min-heap,就是后面的两孩子都要比自己大。若不是,就要swap。 + +还是要记一下min-heap的判断规律:for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. + +siftdown时:在curr node和两个son里面小的比较。如果的确curr < son, 搞定,break while. +但若curr 并不比son小,那么就要换位子,而且继续从son的位子往下面盘查。 + + +--- +**109. [House Robber II.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber%20II.java)** Level: Medium + +和House Robber I 类似, DP. + +根据dp[i-1]是否被rob来讨论dp[i]: dp[i] = Math.max(dp[i-1], dp[i - 2] + nums[i - 1]); + +特别的是,末尾的last house 和 first house相连。这里就需要分别讨论两种情况: +1. 最后一个房子被rob +2. 最后一个房子没被rob + +两种情况做完,综合对比一下. + + +--- +**110. [House Robber III.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber%20III.java)** Level: Hard + +由于无法用简单的方法构造DP array, 所以采取了普通的DFS。 + +The catch: +判断当下的node是否被采用,用一个boolean来表示. + +1. 如果curr node被采用,那么下面的child一定不能被采用。 +2. 如果curr node不被采用,那么下面的children有可能被采用,但也可能略过,所以这里用Math.max() 比较一下两种可能有的dfs结果。 + + + +--- +**111. [House Robber.java](https://github.com/awangdev/LintCode/blob/master/Java/House%20Robber.java)** Level: Easy + +最基本的dp。 +看前一个或前两个的情况,再总和考虑当下的。 +思考的适合搞清楚当下的和之前的情况的关系。 +滚动数组的优化,就是确定了是这类“只和前一两个位子“相关的Fn而推出的。 + + +--- +**112. [Identical Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Identical%20Binary%20Tree.java)** Level: Easy + +Divide, && 每种情况(左右一一对应) +注意 null states + + + +--- +**113. [Implement Queue by Two Stacks.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Queue%20by%20Two%20Stacks.java)** +As the title described, you should only use two stacks to implement a queue's actions. + +The queue should support push(element), pop() and top() where pop is pop the first(a.k.a front) element in the queue. + +Both pop and top methods should return the value of first element. + +Example +For push(1), pop(), push(2), push(3), top(), pop(), you should return 1, 2 and 2 + +Challenge +implement it by two stacks, do not use any other data structure and push, pop and top should be O(1) by AVERAGE. + +Thoughts: +1. Push everything into stack2: whatever comes in last, will be on top. +2. Pop and Top: return stack1's top element. +3. Initially, when stack1 is empty, need to reverse all stack2 and put into stack: like pouring water from cup stack2 into cup stack1. + Or:when stack1 has been top() over, pour stack2 into stack1 again: the stack2's bottom becomes stack1's top, which is correct: returning the oldest element of queue (front of queue) + +Tags Expand +LintCode Copyright Stack Queue +*/ + + +public class Solution { + private Stack stack1; + private Stack stack2; + public void pourS2ToS1(){ + while (!stack2.empty()) { + stack1.push(stack2.peek()); + stack2.pop(); + } + } + public Solution() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public void push(int element) { + stack2.push(element); + } + + public int pop() { + if (stack1.empty()) { + pourS2ToS1(); + } + return stack1.pop(); + } + + public int top() { + if (stack1.empty()) { + pourS2ToS1(); + } + return stack1.peek(); + } +} + + +--- +**114. [Implement Stack by Two Queues.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Stack%20by%20Two%20Queues.java)** +用一个Temp做swap + +做法1: +逻辑在top()/pop()里, 每次换水,查看末尾项. + +做法2: +逻辑在push里面: +1. x 放q2。 +2. q1全部offer/append到q2. +3. 用一个Temp做swap q1, q2. +q1的头,就一直是最后加进去的值. + +--- +**115. [Implement Stack.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Stack.java)** +Data Structure: ArrayList +return/remove ArrayList的末尾项。 + + +--- +**116. [Implement strStr().java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20strStr().java)** +1. border condition。 如果 haystack.length() < needle.length() 的话,必须错。但是这个可以优化省略。 +2. 当S2是“”的时候,也就是能在s1的其实位置找到s2....index = 0. +3. 记得如何在s1里面找s2. 就是把遍历s1的 i , 加上遍历s2的 j。 + +优化: +1. s1, s2长短可以不比较。因为forloop的时候: s1.length() - s2.length() + 1,如果s2长于s1,这里自然就断了。 +2. if(s1.charAT(i+j) == s2.charAT(j)). 可以省略。For loop 里面就Check到这个了。 + +--- +**117. [Implement Trie (Prefix Tree).java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Trie%20(Prefix%20Tree).java)** +如果是遇到一个一个字查询的题,可以考虑一下。 +构建TrieNode的时候要注意:如何找孩子?如果是个map的话,其实就挺好走位的。 +而且,每个node里面的 char 或者string有时候用处不大, +可以为空。但是有些题目,比如在结尾要return一些什么String,就可以在end string那边存一个真的String。 + + + +--- +**118. [Implement Trie.java](https://github.com/awangdev/LintCode/blob/master/Java/Implement%20Trie.java)** Level: Medium + +Tire, 也即是 Prefix Tree. + +HashMap构建Trie。 Trie三个Method:  +1. Inset: 加 word +2. Search: 找word +3. StartWith: 找prefix + +只有两条children的是binary tree. 那么多个children就是Trie。 那么没有left/right pointer怎么找孩子? +用HashMap,以child的label为Key,value就是child node。 HashMap走位 + +Note: +node里的char在这是optional。 +另外有种题目,比如是跟其他种类的search相关,在结尾要return whole string,就可以在node里存一个up-to-this-point的String。 + + + + +--- +**119. [IndexMatch.java](https://github.com/awangdev/LintCode/blob/master/Java/IndexMatch.java)** Level: Easy + +有序, 假设有这样的数字:target. +target 左边的数字,一定不比index大,target右边的数字,一定比index大。 +这样可以binary search.O(logn) + + +--- +**120. [Inorder Successor in Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Inorder%20Successor%20in%20Binary%20Search%20Tree.java)** Level: Medium + +画inorder图,发现规律.每个node的后继node(successor)有几种情况: +1. node.right 是个leaf到底了。那么就return. +2. set rightNode = node.right, 但发现rightNode has a lot left children to leaf. +3. 比如, node.right == null, 也就是node自己是leaf,要回头看山顶找Inorder traversal规则里的下一个。 + 发现:其实就是每层都把路过的curr node放在stack里,最上面的,就是当下改return的那个successor:) Done. + + +--- +**121. [Insert Interval.java](https://github.com/awangdev/LintCode/blob/master/Java/Insert%20Interval.java)** Level: Easy + + +方法1:Scan Line +Interval 拆点,PriorityQueue排点。 +Merge时用count==0作判断点。 + +PriorityQueue: O(logN). 扫n点,总共:O(nLogn) + + +方法2: +O(n) 直接找到可以insert newInterval的位子. Insert。 这里已经给了sorted intervals by start point. 所以O(n) + +然后loop to merge entire interval array + +另外: 因为interval已经sort, 本想用Binary Search O(logn). 但是找到interval insert position, merge还是要用 O(n)。 +比如刚好newInterval cover entire list.... + + + + +--- +**122. [Insert Node in a Binary Search Tree .java](https://github.com/awangdev/LintCode/blob/master/Java/Insert%20Node%20in%20a%20Binary%20Search%20Tree%20.java)** Level: Easy + +往Binary Search Tree里面加东西,一定会找到一个合适的leaf加上去。 + +那么:就是说someNode.left or someNode.right是null时,就是insert node的地方。 + +找到那个someNode就按照正常的Binary Search Tree规律。 + + +--- +**123. [Insertion Sort List.java](https://github.com/awangdev/LintCode/blob/master/Java/Insertion%20Sort%20List.java)** +基本上就是正常的想法:已经有个sorted list, insert一个element进去。怎么做? + while 里面每个元素都小于 curr, keep going + 一旦curr在某个点小了,加进去当下这个空隙。 +这个题目也就是:把list里面每个元素都拿出来,scan and insert一遍! + + +--- +**124. [Integer to English Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Integer%20to%20English%20Words.java)** +Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 2^31 - 1. + +For example, +123 -> "One Hundred Twenty Three" +12345 -> "Twelve Thousand Three Hundred Forty Five" +1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" +Hint: + +Did you see a pattern in dividing the number into chunk of words? For example, 123 and 123000. +Group the number by thousands (3 digits). You can write a helper function that takes a number less than 1000 and convert just that chunk to words. +There are many edge cases. What are some good test cases? Does your code work with input such as 0? Or 1000010? (middle chunk is zero and should not be printed out) +Tags: Math, String +Similar Problems: (M) Integer to Roman + +Thoughts: +2^31 - 1 = 2,147,483,647 +Trillion, Billion, Million, Thousand, Hundred, Ninty .... Ten, Nine ... One, Zero. + +1. Break the words to up to 4 parts: new break[4] by /(1000 ^ i) +2. For each i, deal with that 3-digit number in break[i] +3. Append corresponding words for each break[i] + +Special case: +zero +000 in one break[i]: skip the whole thing +*/ + + +public class Solution { + public String[] v1 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; + public String[] v2 = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; + public String numberToWords(int num) { + if (num < 0) { + return ""; + } + if (num == 0) { + return "Zero"; + } + String rst = ""; + for (int i = 0; i < 4; i++) { + int partial = num - (num / 1000) * 1000; + if (partial > 0) { + rst = helper(partial, i) + " " + rst; + } + num /= 1000; + } + while (rst.charAt(rst.length() - 1) == ' ') { + rst = rst.substring(0, rst.length() - 1); + } + return rst; + } + + public String helper(int num, int i) { + String str = ""; + if (num >= 100) { + int hund = num / 100; + str = v1[hund] + " Hundred "; + num = num % 100; + } + + if (num < 20) { + str += v1[num] + " "; + } else { + int numTens = num / 10; + int numDigit = num % 10; + str += v2[numTens] + " "; + str += v1[numDigit] + " "; + } + + while (str.charAt(str.length() - 1) == ' ') { + str = str.substring(0, str.length() - 1); + } + + //depending on i: + switch (i) { + case 1 : + str += " Thousand"; + break; + case 2 : + str += " Million"; + break; + case 3 : + str += " Billion"; + break; + } + + return str; + } +} + +--- +**125. [Interleaving Positive and Negative Numbers.java](https://github.com/awangdev/LintCode/blob/master/Java/Interleaving%20Positive%20and%20Negative%20Numbers.java)** +这里主要要特别考虑,正数多还是负数多的问题。 +count一下,然后举两个小栗子就看出来端倪了。 +然后Two Pointer + +--- +**126. [Interleaving String.java](https://github.com/awangdev/LintCode/blob/master/Java/Interleaving%20String.java)** +Given three strings: s1, s2, s3, determine whether s3 is formed by the interleaving of s1 and s2. + +Example +For s1 = "aabcc", s2 = "dbbca" + +When s3 = "aadbbcbcac", return true. +When s3 = "aadbbbaccc", return false. +Challenge +O(n2) time or better + +Tags Expand +Longest Common Subsequence Dynamic Programming + +Attempt2: DP[i][j]: boolean that if first S1(i) chars and first S2(j) chars can interleavign first S3(i + j) +Match one char by one char. We have 2 conditions: match s1 or s2 char, Let's do double-for-loop on s1 and s2 +1. match s1: s3.charAt(i + j -1) == s1.charAt(i - 1) && DP[i - 1][j]; // makes sure DP[i-1][j] also works before adding s1[i-1] onto the match list +2. match s2: s3.charAt(i + j -1) == s2.charAt(j - 1) && DP[i][j - 1]// similar as above + +Note: +Need to initiate the starting conditions with just s1, or just s2 +Note2: +DP ususally start i == 1, and always use (i - 1) in the loop... this is all because we are trying to get DP[i][j], which are 1 index more than length +*/ +public class Solution { + public boolean isInterleave(String s1, String s2, String s3) { + if (s3 == null || (s1 == null && s2 == null) || s1.length() + s2.length() != s3.length()) { + return false; + } + boolean[][] DP = new boolean[s1.length() + 1][s2.length() + 1]; + DP[0][0] = true; // empty s1 and s2 would be a working case + + //with just s1: + for (int i = 1; i <= s1.length(); i++) { + if (s3.charAt(i - 1) == s1.charAt(i - 1) && DP[i - 1][0]) { + DP[i][0] = true; + } + } + + //with just s2: + for (int j = 1; j <= s2.length(); j++) { + if (s3.charAt(j - 1) == s2.charAt(j - 1) && DP[0][j - 1]) { + DP[0][j] = true; + } + } + + for (int i = 1; i <= s1.length(); i++) { + for (int j = 1; j <= s2.length(); j++) { + if ((s3.charAt(i + j - 1) == s1.charAt(i - 1) && DP[i - 1][j]) + || (s3.charAt(i + j - 1) == s2.charAt(j - 1) && DP[i][j - 1])) { + DP[i][j] = true; + } + } + } + + return DP[s1.length()][s2.length()]; + } +} + + + + +/* + +Attempt1, Incorrect: tho, magically passed 91% of lintcode, by coincidence +This solution could goes on and on with s1, and failed at certain point when j == 0 does not fit in. +s1 = "sdfjas;dfjoisdu" +s2 = "dfnakd" +s3 = "sdfjas;dfjoisdf..." // Failed at that 'f' in s3 + +Thoughts: +DP[mxn]: loop through S1.length and S2.length, record DP[k] = true or false. +DP[k] = (S1(0~i) + S2(0 ~ j)) is leading S3: index of (xxx) == 0. + +*/ +public class Solution { + + public boolean isInterleave(String s1, String s2, String s3) { + if (s3 == null || (s1 == null && s2 == null) || s1.length() + s2.length() != s3.length()) { + return false; + } + + int i = 0; + int j = 0; + String base = ""; + for (int k = 0; k < s1.length()*s2.length() - 1; k++) { + if (i < s1.length() || j < s2.length()) { + if (i < s1.length() && s3.indexOf(base + s1.charAt(i)) == 0) { + base += s1.charAt(i); + i++; + } else if (j < s2.length() && s3.indexOf(base + s2.charAt(j)) == 0) { + base += s2.charAt(j); + j++; + } else { + return false; + } + } + } + return true; + } +} + +--- +**127. [Intersection of Two Linked Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Intersection%20of%20Two%20Linked%20Lists.java)** Level: Easy + +长短list,找重合点。 +长度不同的话,切掉长的list那个的extra length。 那么起点一样后,重合点就会同时到达。 + + + +--- +**128. [Interval Minimum Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Minimum%20Number.java)** Level: Medium + +SegtmentTree, methods: Build, Query. 这题是在SegmentTreeNode里面存min. + +类似的有存:max, sum, min + + + + +--- +**129. [Interval Sum II.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Sum%20II.java)** Level: Hard + +SegmentTree大集合。记得几个Methods: Build, Query, Modify. 不难。只是要都记得不犯错:) + + +--- +**130. [Interval Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Interval%20Sum.java)** Level: Medium + +其实是segment tree 每个node上面加个sum。 + +记得Segment Tree methods: Build, Query + +Note: 存在SegmentTreeNode里面的是sum. 其他题目可能是min,max ... or something else. + + + +--- +**131. [Invert Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Invert%20Binary%20Tree.java)** Level: Easy + +non-recursive: BFS with queue。 或者regular recurisve - divide and conquer. + + +--- +**132. [Isomorphic Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Isomorphic%20Strings.java)** Level: Easy + +HashMap 来确认match。有几种情况考虑: + +1. Match. 就是map.containsKey, map.containsValue, and char1 == char2. Perfect. + +2. Either Key not exist, or Value not exit. False; + +3. Both key and Value exist, but map.get(char1) != char2. Miss-match. False. + +4. None of Key or Value exist in HashMap. Then add the match. + + +--- +**133. [Jump Game II.java](https://github.com/awangdev/LintCode/blob/master/Java/Jump%20Game%20II.java)** Level: Hard + +Greedy, 图解 http://www.cnblogs.com/lichen782/p/leetcode_Jump_Game_II.html + +维护一个range, 是最远我们能走的. + +index/i 是一步一步往前, 每次当 i <= range, 做一个while loop, 在其中找最远能到的地方 maxRange + +然后更新 range = maxRange + +其中step也是跟index是一样, 一步一步走. + +最后check的condition是,我们最远你能走的range >= nums.length - 1, 说明以最少的Step就到达了重点。Good. + + + +--- +**134. [Jump Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Jump%20Game.java)** Level: Medium + +给出步数,看能不能reach to end. + +Status: +DP[i]: 在i点记录,i点之前的步数是否可以走到i点? True of false. + 其实j in [0~i)中间只需要一个能到达i 就好了 +Function: +DP[i] = DP[j] && (j + A[j]), for all j in [0 ~ i) +Return: + DP[dp.length - 1]; + + +--- +**135. [Kth Largest Element.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Largest%20Element.java)** Level: Medium + +用Quick Sort 里面partion的一部分。 +partion的结果是那个low, 去找 low==nums.size() - k, 也就是倒数第K个。 +没找到继续partion recursively. + +sort的过程是排一个从小到大的list. (同样的代码还可以好xth smallest,mid变成x就好) + +Quick Sort: +每个iteration, 找一个pivot,然后从low,和high都和pivot作比较。 +找到一个low>pivot, high queue = new PriorityQueue(k, + new Comparator(){ + public int compare(Node a, Node b) { + return a.val - b.val; + } + }); + + for (int i = 0; i < matrix.length; i++) { + if (matrix[i].length > 0) { + queue.offer(new Node(matrix[i][0], i, 0)); + } + } + + //Find kth + while (!queue.isEmpty()) { + Node node = queue.poll(); + if(k == 1) { + return node.val; + } + int x = node.x; + int y = node.y; + if (y < matrix[x].length - 1) { + queue.offer(new Node(matrix[x][y+1], x, y+1)); + } + k--; + } + + return -1; + } +} + +--- +**138. [Kth Smallest Sum In Two Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Kth%20Smallest%20Sum%20In%20Two%20Sorted%20Arrays.java)** Level: Hard + + +用priority queue. 每次把最小的展开,移位。分别x+1,或者y+1: +因为当下的Min里面x,y都是最小的。所以下一个最小的不是(x+1,y),就是(x,y+1)。 + +每次就poll()一个,放2个新candidate进去就好了。 +注意,这样的做法会用重复,比如例子(7,4)会出现两次。用一个HashSet挡一下。 + +注意,HashSet的唯一性,用一个"x,y"的string就可以代为解决。 + + +--- +**139. [Largest Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Largest%20Number.java)** +Given a list of non negative integers, arrange them such that they form the largest number. + +Example +Given [1, 20, 23, 4, 8], the largest formed number is 8423201. + +Note + The result may be very large, so you need to return a string instead of an integer. + +Tags Expand +Sort + +Thoughts: +Use a comparator with String.comareTo, then uset Arrays.sort(...) + +*/ + +class CustomComparator implements Comparator { + public int compare(String s1, String s2) { + return (s2 + s1).compareTo(s1 + s2); + } +} +public class Solution { + /** + *@param num: A list of non negative integers + *@return: A string + */ + public String largestNumber(int[] num) { + if (num == null || num.length == 0) { + return ""; + } + String[] strs = new String[num.length]; + for (int i = 0; i < num.length; i++) { + strs[i] = num[i] + ""; + } + Arrays.sort(strs, new CustomComparator()); + StringBuffer sb= new StringBuffer(); + for (int i = 0; i < num.length; i++) { + sb.append(strs[i]); + } + String rst = sb.toString(); + if (rst.charAt(0) == '0') { + return "0"; + } + return rst; + } +} + + + + + + + + + + + + + + + + + + +--- +**140. [Largest Rectangle in Histogram.java](https://github.com/awangdev/LintCode/blob/master/Java/Largest%20Rectangle%20in%20Histogram.java)** +Example +Given height = [2,1,5,6,2,3], +return 10. + +Tags Expand +Array Stack + +Thinking Process: +///TODO: missing thinking process for Largest Rectangle in Histogram + +*/ + +public class Solution { + /** + * @param height: A list of integer + * @return: The area of largest rectangle in the histogram + */ + public int largestRectangleArea(int[] height) { + if (height == null || height.length == 0) { + return 0; + } + Stack stack = new Stack(); + int max = 0; + for (int i = 0; i <= height.length; i++) { + int current = (i == height.length) ? -1 : height[i]; + while (!stack.empty() && current <= height[stack.peek()]) { + int h = height[stack.pop()]; + int w = stack.empty() ? i : i - stack.peek() - 1; + max = Math.max(max, w * h); + } + stack.push(i); + } + return max; + } +} + + +--- +**141. [Last Position of Target.java](https://github.com/awangdev/LintCode/blob/master/Java/Last%20Position%20of%20Target.java)** +--- +**142. [Length of Last Word.java](https://github.com/awangdev/LintCode/blob/master/Java/Length%20of%20Last%20Word.java)** +Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. + +If the last word does not exist, return 0. + +Example +Given s = "Hello World", return 5. + +Note +A word is defined as a character sequence consists of non-space characters only. + +Tags Expand +String + +Thoughts: +1. Split by space +2. return last word's length + +Note: Java split: have to add '\\' in order to pass the key word. +*/ + + + +public class Solution { + /** + * @param s A string + * @return the length of last word + */ + public int lengthOfLastWord(String s) { + if (s == null || s.length() == 0) { + return 0; + } + String[] arr = s.split("\\ "); + String lastWord = arr[arr.length - 1]; + + return lastWord.length(); + } +} + +--- +**143. [Letter Combinations of a Phone Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Letter%20Combinations%20of%20a%20Phone%20Number.java)** Level: Medium + +方法1: Iterative with BFS using queue. + +方法2: Recursively adding chars per digit + + +--- +**144. [Linked List Cycle II.java](https://github.com/awangdev/LintCode/blob/master/Java/Linked%20List%20Cycle%20II.java)** + + +O(1)要首先break while loop when there is a slow==fast +然后,然后就有个我不懂得地方: + +当head == slow.next时候, head就是cycle starting point. +也就是说,当slow 移动到了那个回溯点,slow.next那个点就刚好是head的那个点... + +这个可能要写一写,装一装,证明证明才行...不是特别清楚。 + +--- +**145. [Linked List Cycle.java](https://github.com/awangdev/LintCode/blob/master/Java/Linked%20List%20Cycle.java)** +那个时候其实slow.val = fast.val. + +O(n):用HashMap,一直add elements. 如果有重复,那么很显然是有Cycle le + +--- +**146. [Longest Common Prefix.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Prefix.java)** Level: Medium + +Nested loop, 每一次比较所有string 同位是否相等。 + +相等,append string. 不等,return. + + +--- +**147. [Longest Common Subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Subsequence.java)** +Given two strings, find the longest comment subsequence (LCS). + +Your code should return the length of LCS. + +Example +For "ABCD" and "EDCA", the LCS is "A" (or D or C), return 1 + +For "ABCD" and "EACB", the LCS is "AC", return 2 + +Clarification +What's the definition of Longest Common Subsequence? + + * The longest common subsequence (LCS) problem is to find the longest subsequence common to all sequences in a set of sequences (often just two). (Note that a subsequence is different from a substring, for the terms of the former need not be consecutive terms of the original sequence.) It is a classic computer science problem, the basis of file comparison programs such as diff, and has applications in bioinformatics. + + * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem + +Tags Expand +LintCode Copyright Longest Common Subsequence Dynamic Programming + +Thinking process: +Using DP. +check[i][j] means: the length of longest common subsequnce between A(0 ~ i) and B(0 ~ j). +Then there are two ways to reach check[i][j]: +1. A(i-1) == B(j - 1), then check[i][j] = check[i - 1][j - 1] + 1; +2. A(i-1) != B(j - 1), then pick the max between (i-1,j) , (i,j-1) and (i, j ) +Note: check[][] is initialized with all 0's. Index (0,0) is used as starting 0. +*/ +public class Solution { + /** + * @param A, B: Two strings. + * @return: The length of longest common subsequence of A and B. + */ + public int longestCommonSubsequence(String A, String B) { + if (A == null || B == null || A.length() == 0 || B.length() == 0) { + return 0; + } + int[][] check = new int[A.length() + 1][B.length() + 1]; + for (int i = 1; i <= A.length(); i++) { + for (int j = 1; j <= B.length(); j++) { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + check[i][j] = check[i - 1][j - 1] + 1; + } else { + check[i][j] = Math.max(check[i][j], check[i - 1][j]); + check[i][j] = Math.max(check[i][j], check[i][j - 1]); + } + } + } + return check[A.length()][B.length()]; + } +} + + + +--- +**148. [Longest Common Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Common%20Substring.java)** +Given two strings, find the longest common substring. + +Return the length of it. + +Example +Given A = "ABCD", B = "CBCE", return 2. + +Note +The characters in substring should occur continuously in original string. This is different with subsequence. + +Challenge +O(n x m) time and memory. + +Tags Expand +LintCode Copyright Longest Common Subsequence Dynamic Programming + +Thoughts: +1. Compare all i X j. +2. Use a D[i][j] to mark the amount of common substring based on D[i - 1][j -1]. Could be 0. +3. track max length + +NOTE1: create 2D array that's [N + 1][M + 1] because we want to hold D[n][M] in the 2d array +NOTE2: be carefule with init index 0's + +*/ + + +public class Solution { + /** + * @param A, B: Two string. + * @return: the length of the longest common substring. + */ + public int longestCommonSubstring(String A, String B) { + if (A == null || B == null || A.length() == 0 || B.length() == 0) { + return 0; + } + int [][] D = new int[A.length() + 1][B.length() + 1]; + int max = 0; + for (int i = 0; i <= A.length(); i++) { + for(int j = 0; j <= B.length(); j++) { + if (i == 0 || j == 0) { + D[i][j] = 0; + } else { + if (A.charAt(i - 1) == B.charAt(j - 1)) { + D[i][j] = D[i - 1][j - 1] + 1; + } else { + D[i][j] = 0; + } + max = Math.max(max, D[i][j]); + } + } + } + return max; + } +} + +--- +**149. [Longest Consecutive Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Consecutive%20Sequence.java)** +Given an unsorted array of integers, find the length of the longest consecutive elements sequence. + +For example, +Given [100, 4, 200, 1, 3, 2], +The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. + +Your algorithm should run in O(n) complexity. + +Hide Tags Array + +Thinking process: +0. This problem can be done using sorting, but time complexity of sorting is O(nlogn). This problem requires O(n). +1. Want to check if a number's left and right is consecutive to itself, but cannot do it due to the given unsorted array: think about a Hashmap. +2. HashMap(Key, Value) = (the number itself, boolean: have been counted or not). If you count a number as a consecutive, you only need to count it once. +3. How HashMap works: + when checking a number's consecutive, look at number--, number++, see if they are in the HashMap. If exist, means consecutive. + If a number exist in the hashmap and its value is 'true', then we need to skip this number beacuse it has been checked. +4. Track the total number consecutives of 1 perticular number, compare it with the maxL. Save the Math.max to maxL. +5. Depending on the problem, we can store a consecutive sequence or simply just its length: maxL. This problem wants the maxL. +*/ + +public class Solution { + public int longestConsecutive(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + int maxL = 1; + HashMap history = new HashMap(); + for (int i : num) { + history.put(i, false); + } + for (int i : num) { + if (history.get(i)) { + continue; + } + //check ++ side + int temp = i; + int total = 1; + while (history.containsKey(temp + 1)) { + total++; + temp++; + history.put(temp, true); + } + //check -- side + temp = i; + while (history.containsKey(temp - 1)) { + total++; + temp--; + history.put(temp, true); + } + maxL = Math.max(maxL, total); + } + return maxL; + } +} + + + +/* +10.19.2015 +Thougths: +1. sort +2. use a 'count' and 'max' to keep track of consecutive elements +3. one-pass + +Note: +Take care of equal numbers: skip/continue those + +*/ + +public class Solution { + /** + * @param nums: A list of integers + * @return an integer + */ + public int longestConsecutive(int[] num) { + if (num == null || num.length == 0) { + return 0; + } + if (num.length == 1) { + return 1; + } + int count = 1; + int max = 1; + Arrays.sort(num); + for (int i = 1; i < num.length; i++) { + if (num[i - 1] == num[i]) { + continue; + } else if (num[i - 1] + 1 == num[i]) { + count++; + max = Math.max(count, max); + } else { + count = 1; + } + } + return max; + } +} + +--- +**150. [Longest Increasing Continuous subsequence II.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Continuous%20subsequence%20II.java)** +O(mn) runtime because each spot will be marked once visited. +这个题目的简单版本一个array的例子:从简单题目开始想DP会简单一点。每个位置,都是从其他位置(上下左右)来的dpValue + 1. 如果啥也没有的时候,init state 其实都是1, 就一个数字,不增不减嘛。 + +--- +**151. [Longest Increasing Continuous subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Continuous%20subsequence.java)** +O(1)是用了两个int来存:每次到i点时,i点满足条件或不满足条件所有的longestIncreasingContinuousSubsequence. +特点:返跑一回,ans还是继续和left轮的ans作比较;求的所有情况的最大值嘛。 + +--- +**152. [Longest Increasing Subsequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Increasing%20Subsequence.java)** +每次都考虑o~i的所有情况。所以double for loop + +--- +**153. [Longest Palindromic Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Palindromic%20Substring.java)** Level: Medium + +方法1: 从中间劈开. 遍历i,从n个不同的点劈开:每次劈开都看是否可以从劈开出作为palindromic的中点延伸。 + Worst case: 整个string都是相同字符,time complexity变成: 1 + 2 +3 + ... +n = O(n^2) + +方法2: 穷举double for loop. O(n^2) + + + +--- +**154. [Longest Substring with At Most K Distinct Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Substring%20with%20At%20Most%20K%20Distinct%20Characters.java)** Level: Medium + +大清洗 O(nk) +map.size一旦>k,要把longest string最开头(marked by pointer:start)的那个char抹掉 +一旦某一个char要被清除,所以在这个char 的1st and last appearance之间的char都要被清洗from map + + + + +--- +**155. [Longest Substring Without Repeating Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Substring%20Without%20Repeating%20Characters.java)** Level: Medium + + +方法2:用两个pointer, head和i. + HashMap: + head从index 0 开始。若没有重复char, 每次只有for loop的i++。每次取substring[head,i]作为最新的string. + 一旦有重复,那么意味着,从重复的老的那个index要往后加一格开始。所以head = map.get(i) +1. + + +注意:head很可能被退回到很早的地方,比如abbbbbba,当遇到第二个a,head竟然变成了 head = 0+1 = 1. +当然这是不对的,所以head要确保一直增长,不回溯。 + + +方法1:只要有non-existing char就count++. 一旦有重复char: + i = 新出现重复Char的位置. + 重新init HashMap, count. + +这个方法每次都把map打碎重来, 是可以的,也没什么不好。就是在for里面改i,自己觉得不太顺.方法二可能顺一点。 + + + + +--- +**156. [Longest Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Longest%20Words.java)** +Given a dictionary, find all of the longest words in the dictionary. + +Example +Given + +{ + "dog", + "google", + "facebook", + "internationalization", + "blabla" +} +the longest words are(is) ["internationalization"]. + +Given + +{ + "like", + "love", + "hate", + "yes" +} +the longest words are ["like", "love", "hate"]. + +Challenge +It's easy to solve it in two passes, can you do it in one pass? + +Tags Expand +Enumeration String LintCode Copyright + +Thoughts: +Two pass: 1st, get longest length. 2nd pass, get all words. + +One pass: +1. Use hashmap: > +2. keep track of the longest length + +Review: +Map: put, get +ArrayList: add +We can get a value from map, and change directly on it, if that's an object (basically refer to the original object) +*/ + + +class Solution { + /** + * @param dictionary: an array of strings + * @return: an arraylist of strings + */ + ArrayList longestWords(String[] dictionary) { + if (dictionary == null || dictionary.length == 0) { + return null; + } + HashMap> map = new HashMap>(); + int longestLength = 0; + + for (int i = 0; i < dictionary.length; i++) { + int strLength = dictionary[i].length(); + if (map.containsKey(strLength)) { + map.get(strLength).add(dictionary[i]); + } else { + ArrayList list = new ArrayList(); + list.add(dictionary[i]); + map.put(strLength, list); + } + longestLength = strLength > longestLength ? strLength : longestLength; + } + return map.get(longestLength); + } +}; + +--- +**157. [Lowest Common Ancestor II.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor%20II.java)** Level: Easy + +这个题有个奇葩的地方,每个node还有一个parent。 所以可以自底向上. + +1. 曾经做的hashset的优化,找到的都存hashset. exist就return那个duplicate. + + +2. 普通做法:2 lists。 + 自底向上。利用parent往root方向返回。 + +注意:无法从root去直接搜target node 而做成两个list. 因为根本不是Binary Search Tree! + + + +--- +**158. [Lowest Common Ancestor of a Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor%20of%20a%20Binary%20Search%20Tree.java)** Level: Medium + +利用 BST的性质,可以直接搜到target node,而做成两个长度不一定相等的list。然后很简单找到LCA + + + +--- +**159. [Lowest Common Ancestor.java](https://github.com/awangdev/LintCode/blob/master/Java/Lowest%20Common%20Ancestor.java)** Level: Easy + +普通的Binary Tree,node child 自顶向下蔓延。 + +方法1:O(1) sapce O(h). Recursive. 循环的截点是: +当root == null或者 A B 任何一个在findLCA底部被找到了(root== A || root == B),那么就return 这个root. + +三种情况: +1. A,B都找到,那么这个level的node就是其中一层的parent。其实,最先recursively return到的那个,就是最底的LCA parent. +2. A 或者 B 找到,那就还没有公共parent,return 非null得那个。 +3. A B 都null, 那就找错了没有呗, return null + + +//无法找到target element, 因为不是Binary Search Tree +//[Not Working]:O(n) space O(h) time。把两条线binary search出来。找第一个不同的parent. 代码长。 Iterative + + +--- +**160. [LRU Cache.java](https://github.com/awangdev/LintCode/blob/master/Java/LRU%20Cache.java)** Level: Hard + + +timeout method, 天真的来了一个O(n) 的解法,结果果然timeout. +一个map存数值。一个queue来存排位。 +每次有更新,就把最新的放在末尾;每次超过capaticity,就把大头干掉。很简单嘛,但是跑起来太久,失败了。 + +于是就来了第二个做法。其实还是跟方法一是类似的。 +用了一个特别的双向的LinkNode,有了head和tail,这样就大大加快了速度。 +主要加快的就是那个‘更新排位’的过程,过去我是O(n),现在O(1)就好了。 + +巧妙点: +1. head和tail特别巧妙:除掉头和尾,和加上头和尾,就都特别快。 +2. 用双向的pointer: pre和next, 当需要除掉任何一个node的时候,只要知道要除掉哪一个, +直接把node.pre和node.next耐心连起来就好了,node就自然而然的断开不要了。 + +一旦知道怎么解决了,就不是很特别,并不是难写的算法: +moveToHead() +insertHead() +remove() + + +--- +**161. [Majority Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number%20II.java)** Level: Medium + +分三份:a b c考虑。若a, countA++, 或b, countB++,或c,countA--,countB--. + +最后出现的两个count>0的a和b,自然是potentially大于1/3的。其中有一个大于1/3. + +比较a和b哪个大,就return哪一个。 + + +--- +**162. [Majority Number III.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number%20III.java)** Level: Medium + +与其他Majority Number一样。 + +出现次数多余1/k,就要分成k份count occurance.用HashMap。 存在的+1;不存在map里的,分情况: +若map.size() == k,说明candidate都满了,要在map里把所有现存的都-1; +若map.size() < k, 说明该加新candidate,那么map.put(xxx, 1); + +最后在HashMap里找出所留下的occurance最大的那个数。 + + +--- +**163. [Majority Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Majority%20Number.java)** Level: Easy + +Majority Number是指超半数。任何超半数,都可以用0和1count:是某个number,+1;不是这个number,-1. + +注意:assume valid input, 是一定有一个majority number的。否则此法不成。[1,1,1,2,2,2,3]是个invalid input,结果是3,当然也错了。 + +Majority Number II,超1/3, 那么就分三份处理,countA, countB来计算最多出现的两个。 + +Majority Number III, 超1/k, 那么自然分k份。这里用到 HashMap。 + + +--- +**164. [Matrix Zigzag Traversal.java](https://github.com/awangdev/LintCode/blob/master/Java/Matrix%20Zigzag%20Traversal.java)** Level: Easy + +分析4个step:right, left-bottom,down,right-up +implement时注意index.有点耐心 + + +--- +**165. [Max Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Max%20Tree.java)** Level: Hard + +Should memorize MaxTree. 依次类推,会做Min-Tree, Expression Tree + +Stack里,最大的值在下面。利用此性质,有这样几个step: + +1 +把所有小于curr node的,全Pop出来, while loop, keep it going. +最后pop出的这个小于Curr的node:它同时也是stack里面pop出来小于curr的最大的一个,最接近curr大小。(因为这个stack最大值靠下面) +把这个最大的小于curr的node放在curr.left. + +2 +那么,接下去stack里面的一定是大于curr: +那就变成curr的left parent. set stack.peek().right = curr. + +3 +结尾:stack底部一定是最大的那个,也就是max tree的头。 + + + + +--- +**166. [Maximal Square.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximal%20Square.java)** Level: Medium + +DP问题 + +从边长为2的正方形看起,看左上角的那个点。 +如何确定是个正方形?首先看左上点是不是1,然后看右边,右下,下面的点是不是1. + +DP就是根据这个特征想出来。dp[i,j]: 从右下往左上推算,包括当前点在内的所能找到的最大边长。 + 注意dp[i,j]被右边,右下,下面三点的最短点所限制。这就是fn. + +Init: + 把右边,下边两个边缘init一遍,存matrix在这两条边上的值,代表的意思也就是dp[i][j]在这些点上的初始值:变成为1 or 0. + + +--- +**167. [Maximum Depth of Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Depth%20of%20Binary%20Tree.java)** Level: Easy + +DFS: Divide and conquer. 维持一个最大值。 + + +--- +**168. [Maximum Product Subarray.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Product%20Subarray.java)** +Find the contiguous subarray within an array (containing at least one number) which has the largest product. + +Example +For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6. + +Tags Expand +Dynamic Programming Subarray +*/ +/* +Attempt2: Use a max array and a min array. (http://www.jiuzhang.com/solutions/maximum-product-subarray/) +This is similar to my original attempt1, but saves a lot memory space. + +0. Max array is always positive, Min array is always negative. Use these 2 arrays to keep track of largest positive number and smallest negative number +1. When current nums[i] > 0, use max[i - 1] * nums[i]. +2. When current nums[i] < 0, user min[i - 1] * nums[i]; +3. Don't for get to calculate both max and min for each i, for next iteration to use. + +In either case, we will produce largest possible product. + +Trick: depending on nums[i] is positive or negative, calculate differently ... +*/ + +public class Solution { + public int maxProduct(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int[] max = new int[nums.length]; + int[] min = new int[nums.length]; + max[0] = nums[0]; + min[0] = nums[0]; + int rst = max[0]; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > 0) { + max[i] = Math.max(nums[i], max[i - 1] * nums[i]);//the nums[i] could just be the best option + min[i] = Math.min(nums[i], min[i - 1] * nums[i]); + } else { + max[i] = Math.max(nums[i], min[i - 1] * nums[i]); + min[i] = Math.min(nums[i], max[i - 1] * nums[i]); + } + rst = Math.max(rst, max[i]); + } + return rst; + } +} + + + +/* +Attempt1 thoughts: +97% correct. However, this exceeds memory, basically the DP[][] is too large. +Draw a 2D array: +Row: Start from a number ROW[i], what contiguous value can we get: + 0 1 2 3 + ------------- + 2 3 -2 4 +0| 2 2 6 -12 -48 +1| 3 x x -6 -24 +2| -2 x x x -8 +3| 4 x x x x + +Look, according to the rules of (contiguous subarray), we can't do Row[i]xRow[i], so we have to do: Row[i]xROW[i+1]xROW[i+2]...etc +Goal: find the max in DP +1. Define DP[0][0] = nums[0]; +2. DP[i][j] = DP[i][j - 1] * nums[j] +3. And we keep track of the max value + +Note: j will always > i, so cases that i >= j are not necessary. +*/ + + +public class Solution { + /** + * @param nums: an array of integers + * @return: an integer + */ + public int maxProduct(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int[][] DP = new int[nums.length][nums.length]; + DP[0][0] = nums[0]; + int max = DP[0][0]; + + for (int i = 0; i < nums.length; i++) { + for (int j = 1; j < nums.length; j++) { + if (i == j) { + DP[i][j] = nums[j]; + } + if (j > i) { + if (DP[i][j - 1] == 0) { + DP[i][j] = nums[j]; + } else { + DP[i][j] = DP[i][j - 1] * nums[j]; + } + max = Math.max(max, DP[i][j]); + } + max = Math.max(max, nums[j]); + } + } + return max; + } +} + +--- +**169. [Maximum Subarray III.java](https://github.com/awangdev/LintCode/blob/master/Java/Maximum%20Subarray%20III.java)** + +Given an array of integers and a number k, find k non-overlapping subarrays which have the largest sum. + +The number in each subarray should be contiguous. + +Return the largest sum. + +Have you met this question in a real interview? Yes +Example +Given [-1,4,-2,3,-2,3], k=2, return 8 + +Note +The subarray should contain at least one number + +Tags Expand +LintCode Copyright Dynamic Programming Subarray Array +*/ + +/* + NOT DONE +*/ +public class Solution { + /** + * @param nums: A list of integers + * @param k: An integer denote to find k non-overlapping subarrays + * @return: An integer denote the sum of max k non-overlapping subarrays + */ + public int maxSubArray(ArrayList nums, int k) { + // write your code + } +} + + +--- +**170. [MaximumSubarray.java](https://github.com/awangdev/LintCode/blob/master/Java/MaximumSubarray.java)** +然后presum[j] - presum[i- 1] 就是 (i,j)之间的和。 + +--- +**171. [MaximumSubarrayII.java](https://github.com/awangdev/LintCode/blob/master/Java/MaximumSubarrayII.java)** +注意:右边算prefix sum, 看上去好像是什么postfix sum? 其实不是。其实都和prefix一样。 +我们需要的那部分prefix sum,其实就是一段数字的总和。 +所以从右边累计上来的。也是一样可以的。 + +--- +**172. [Median of two Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Median%20of%20two%20Sorted%20Arrays.java)** Level: Hard + +Not done + + +--- +**173. [Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Median.java)** +Given a unsorted array with integers, find the median of it. + +A median is the middle number of the array after it is sorted. + +If there are even numbers in the array, return the N/2-th number after sorted. + +Example +Given [4, 5, 1, 2, 3], return 3 + +Given [7, 9, 4, 5], return 5 + +Challenge +O(n) time. + +Tags Expand +LintCode Copyright Quick Sort Array + + +*/ +/* + Recap 12.09.2015. + O(n) means just run through it. It's similar to Partition array: it tries to split the list into 2 parts, and find the pivot. +*/ + +/* +Thoughts: +Use standard quick sort, but the goal is to look for the middle point. +1. Get middle point: remember to -1 because we are looking for position, rather than length. +2. Increase low pointer until find a point >= piviot +3. Decrease high pointer until find a point < poviot +4. Swap the low and high: this set the first value greather than pivot to the right, and first avlue less than pivot to the left. +5. after low and high pointer meets, swap low with the piviot: simply because pivot should be the break point of low and high +6. at the end, the low sould be the middle point, which is the point we are looking for. return corresponding recursive helper. + +*/ +public class Solution { + /** + * @param nums: A list of integers. + * @return: An integer denotes the middle number of the array. + */ + public int median(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + if (nums.length % 2 == 0) { + return helper(nums, 0, nums.length - 1, nums.length/2 - 1); + } else { + return helper(nums, 0, nums.length - 1, nums.length/2); + } + } + + public void swap(int[] nums, int x, int y){ + int temp = nums[x]; + nums[x] = nums[y]; + nums[y] = temp; + } + + public int helper(int[] nums, int start, int end, int mid) { + int pivot = end; + int num = nums[pivot]; + int low = start; + int high = end; + while (low < high) { + while(low < high && nums[low] < num) { + low++; + } + while(low < high && nums[high] >= num) { + high--; + } + swap(nums, low, high); + } + swap(nums, low, pivot); + if (low == mid) { + return nums[low]; + } else if (low < mid) { + return helper(nums, low + 1, end, mid); + } else { + return helper(nums, start, low - 1, mid); + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + +--- +**174. [Meeting Rooms II.java](https://github.com/awangdev/LintCode/blob/master/Java/Meeting%20Rooms%20II.java)** Level: Medium + + +方法1:PriorityQueue + 一个Class来解决。O(nlogn) + +方法2:这里有尝试了一下用一个sorted Array + HashMap: 也还行,但是handle edge的时候,HashMap 要小心,因为相同时间start和end的map key 就会重复了。 + + +--- +**175. [Meeting Rooms.java](https://github.com/awangdev/LintCode/blob/master/Java/Meeting%20Rooms.java)** Level: Easy + +Scan line, class Point{pos, flag}, PriorityQueue排序。计算count + +注意接头点要考虑所有开会结会的情况,不要恰巧漏掉相接的点。 +开会的是超人。瞬间移动接上下一个会议。 + + +--- +**176. [Merge Intervals.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Intervals.java)** Level: Easy + +方法1:O(nlogn) +扫描线+Count无敌手。注意start end把interval给合起来。 +count==0的时候,就是每次start end双数抵消的时候,就应该是一个interval的开头/结尾。写个例子就知道了。 + +空间:O(2n) -> O(n) +时间,priorityqueue: O(nlogn) + +记得怎么写comparator + +在 LeetCode里面,Scan line比方法2要快很多. + +方法2: +Collections.sort() on interval.start之后,试着跑一遍,按照merge的需求,把需要merge的地方续好,然后减掉多余的interval就好。 + +(不知为何LeetCode把Merge Interval, Insert Interval 标为Hard) + +Collections.sort(..., new comparator): sort by Interval.start. + +画两个相连的Interval, prev, curr: +prev只有 prev.end覆盖了 curr.start, 才需要merge. 那么比较一下, marege. +记得如果merge, 一定要list.remove(i), 并且i--, 因为改变了List的大小。 + +若没有重合,就继续iteration: prev = curr. move on. + +/* + new Comparator(){ + public int compare(obj1, obj2) { + return obj1.x - obj2.x; + } + + } +*/ + + + +--- +**177. [Merge k Sorted Arrays.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20k%20Sorted%20Arrays.java)** Level: Medium + +由Merge k sorted list启发。用PriorityQueue,存那k个首发element。 + +PriorityQueue需要存储单位。自己建一个Class Node 存val, x,y index. +因为array里没有 'next' pointer,只能存x,y来推next element + + +--- +**178. [Merge k Sorted Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20k%20Sorted%20Lists.java)** Level: Medium + +用Priorityqueue来排列所有list的leading node. + +记得k lists 需要是已经sort好的。 + +时间:n*O(logk) +PriorityQueue: logk + +这个题目可以有好几个衍生: + 比如,如果k很大,一个机器上放不下所有的k list怎么办? + 比如,如果Merge起来的很长,一个机器上放不下怎么办? + + +--- +**179. [Merge Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Sorted%20Array%20II.java)** + +--- +**180. [Merge Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Sorted%20Array.java)** Level: Easy + +A够长,那么可以从A的尾部开始加新元素。 +注意,从尾部,是大数字优先的。 + + +--- +**181. [Merge Two Sorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Two%20Sorted%20List.java)** Level: Easy + +小的放前。每次比head大小。 +while过后,把没完的list一口气接上。 + +一开始建一个node用来跑路, 每次都存node.next = xxx。存一个dummy。用来return dummy.next. + + +--- +**182. [Merge Two Sorted Lists.java](https://github.com/awangdev/LintCode/blob/master/Java/Merge%20Two%20Sorted%20Lists.java)** +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. + +Tags: Linked List +Similar Problems: (H) Merge k Sorted Lists, (E) Merge Sorted Array, (M) Sort List, (M) Shortest Word Distance II + +*/ + +/* +Thouhts: +Loop throgh both list. Make sure to check the border cases +*/ + + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { val = x; } + * } + */ +public class Solution { + public ListNode mergeTwoLists(ListNode l1, ListNode l2) { + if (l1 == null && l2 == null) { + return null; + } + ListNode node = new ListNode(0); + ListNode dummy = node; + while (l1 != null || l2 != null) { + if (l1 == null) { + node.next = l2; + break; + } else if (l2 == null) { + node.next = l1; + break; + } else { + if (l1.val < l2.val) { + node.next = l1; + l1 = l1.next; + } else { + node.next = l2; + l2 = l2.next; + } + node = node.next; + } + }//end while + return dummy.next; + } +} + +--- +**183. [Middle of Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Middle%20of%20Linked%20List.java)** + +不在乎slow是不是到底,因为fast肯定先到。 +确保fast, fast.next不是Null就好 + + +return slow + +--- +**184. [Min Stack.java](https://github.com/awangdev/LintCode/blob/master/Java/Min%20Stack.java)** Level: Easy + +双Stack:一个正常stack,另一个minStack存当下level最小值. 注意维护minStack的变化 + +另外. 如果要maxStack,也是类似做法 + + +--- +**185. [Minimum Height Trees.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Height%20Trees.java)** +For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels. + +Format +The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels). + +You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + +Example 1: + +Given n = 4, edges = [[1, 0], [1, 2], [1, 3]] + + 0 + | + 1 + / \ + 2 3 +return [1] + +Example 2: + +Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] + + 0 1 2 + \ | / + 3 + | + 4 + | + 5 +return [3, 4] + +Show Hint +Note: + +(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.” + +(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf. + +Credits: +Special thanks to @peisi for adding this problem and creating all test cases. + +Hide Company Tags Google +Hide Tags Breadth-first Search Graph +Hide Similar Problems (M) Course Schedule (M) Course Schedule II + +*/ + + +/* + Starting from leaf with depth == 1, + remove all leaf, and the edge + Till the end, whatever node left, should be the root. + + * WHen there is only 1,2 nodes remaining. that's the rst. + + Put Node in HahsMap + + Iterative over map till map.size() <= 2 + + border n == 2,1, just returl rst. + edges == null, return null. + edges.length == 1, reutrn list +*/ + +public class Solution { + public List findMinHeightTrees(int n, int[][] edges) { + List rst = new ArrayList(); + if (n == 1) { + rst.add(0); + return rst; + }else if (n == 0 || edges == null || edges.length == 0 || edges.length != n - 1) { + return rst; + } + + //populate map + boolean[] nodes = new boolean[n]; + HashMap> map = new HashMap>(); + for (int i = 0; i < n; i++) { + map.put(i, new ArrayList()); + nodes[i] = true; + } + for (int i = 0; i < edges.length; i++) { + if (!map.get(edges[i][0]).contains(edges[i][1])) { + map.get(edges[i][0]).add(edges[i][1]); + } + if (!map.get(edges[i][1]).contains(edges[i][0])) { + map.get(edges[i][1]).add(edges[i][0]); + } + } + + //Remove list with leng == 1 + Queue queue = new LinkedList(); + while (n > 2) { + for (Map.Entry> entry : map.entrySet()) { + if (entry.getValue().size() == 1) { + queue.offer(entry.getKey()); + } + } + while (!queue.isEmpty()) { + n--; + Integer key = queue.poll(); + nodes[key] = false; + int from = map.get(key).get(0); + map.get(from).remove(key); + map.get(key).remove(0); + + } + } + + //Put remaining into rst + for (int i = 0; i < nodes.length; i++) { + if (nodes[i]) { + rst.add(i); + } + + } + + return rst; + } +} + +--- +**186. [Minimum Path Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Path%20Sum.java)** +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. + +Note +You can only move either down or right at any point in time. + +Example +Tags Expand +Dynamic Programming + +Thinking process: +1. Check null, lenght == 0 +2. Min Sum = sum of array. Initialization is a bit different, for example: each row element is added up from previous elemenet. (Not simple value assign from given grid) + - Assign (0,0) to grid[0][0] + - Row 1st row and 1st col, add up values +3. f(x,y) = sum of path value. f(x,y) = Math.Min(f(x-1,y), f(x, y-1)) +4. return f(r-1)(c-1) + +*/ + + +public class Solution { + /** + * @param grid: a list of lists of integers. + * @return: An integer, minimizes the sum of all numbers along its path + */ + public int minPathSum(int[][] grid) { + + if (grid == null || grid.length == 0 || grid[0].length == 0) { + return 0; + } + int row = grid.length; + int col = grid[0].length; + int[][] matrix = new int[row][col]; + matrix[0][0] = grid[0][0]; + //Add up for 1st row && 1st col + for (int i = 1; i < row; i++) { + matrix[i][0] = matrix[i - 1][0] + grid[i][0]; + } + for (int j = 1; j < col; j++) { + matrix[0][j] = matrix[0][j - 1] + grid[0][j]; + } + //Evaluate + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + matrix[i][j] = Math.min(matrix[i - 1][j], matrix[i][j - 1]) + + grid[i][j]; + } + } + return matrix[row - 1][col - 1]; + + } +} + + + +--- +**187. [Minimum Size Subarray Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Size%20Subarray%20Sum.java)** Level: Medium + +2 pointer, O(n). 找subarray, start 或 end pointer,每次一格这样移动. + +好的策略: 先找一个solution, 定住end, 然后移动start; 记录每个solution if occurs; 然后再移动end,往下找。 + +Note: 虽然一眼看上去是nested loop.但是分析后,发现其实就是按照end pointer移动的Loop。start每次移动一格。总体上,还是O(n) + + +Note done the O(nlogn) yet + + +--- +**188. [Minimum Subarray.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Subarray.java)** +Given an array of integers, find the subarray with smallest sum. + +Return the sum of the subarray. + +Example +For [1, -1, -2, 1], return -3 + +Note +The subarray should contain at least one integer. + +Tags Expand +Greedy LintCode Copyright Subarray Array + +Thoughts: +Note: sub-array has order. It's not sub-set +1. On each index: decide to add with nums.get(i), to use the new lowest value nums.get(i). That means: + If the new value is negative (it has decresing impact on sum) and the sum is larger than new value, just use the new value. + In another case, if sum has been nagative, so sum + new value will be even smaller, then use sum. +2. Every time compare the currMin with the overall minimum value, call it minRst. + +Note: remember to pre-set init value for curMin, minRst. +*/ + + +public class Solution { + /** + * @param nums: a list of integers + * @return: A integer indicate the sum of minimum subarray + */ + public int minSubArray(ArrayList nums) { + if (nums == null || nums.size() == 0) { + return 0; + } + int curMin = nums.get(0); + int minRst = nums.get(0); + for (int i = 1; i < nums.size(); i++) { + curMin = Math.min(nums.get(i), curMin + nums.get(i)); + minRst = Math.min(curMin, minRst); + } + return minRst; + } +} + +--- +**189. [Minimum Window Substring.java](https://github.com/awangdev/LintCode/blob/master/Java/Minimum%20Window%20Substring.java)** Level: Hard + +LeetCode Hard +LintCode M, 测试有问题,即使做错也能过. + +基本思想: 用个map存target的。 然后在搜索s的时候,遇到Match, frequency--. +一旦map里面的frequency都被减为0, 就说明找到candidate. + +有好几个trick:考虑start,前指针怎么移动;考虑start在candidate首字母没有多余前,不能移动;考虑candidate出现的情况... + +复习时,回去看别人网站和自己的thoughts + + +--- +**190. [MinimumDepthOfBinaryTree.java](https://github.com/awangdev/LintCode/blob/master/Java/MinimumDepthOfBinaryTree.java)** Level: Easy + +Divide and Conquery一个最小值. 注意处理Leaf的null, 用Integer.MAX_VALUE代替,这样可以避免错误counting. + + +--- +**191. [Missing Ranges.java](https://github.com/awangdev/LintCode/blob/master/Java/Missing%20Ranges.java)** +自己做的时候,想的太复杂,做起了binarysearch,企图节省时间。 +下次要算清楚,是否有意义。 +binarySearch的确logn,但是在lower 和upper之间的数字,很可能还是O(n). +因此一开始就for一遍也是O(n), 而code会相对来说简单许多。 + +想法: +两个pointer, 每次计较prev和curr之间的部分。 +然后prev = curr,向前移动一格。 + + +--- +**192. [Multiply Strings.java](https://github.com/awangdev/LintCode/blob/master/Java/Multiply%20Strings.java)** Level: Medium + +想法不难。turn into int[], 然后每个位子乘积,然后余数carrier移位。 + +但是做起来有很多坑。适合面试黑。 + +1. 数字‘123’, 在数组里面, index == 0 是 ‘1’。 但是我们平时习惯从最小位数开始乘积,就是末尾的'3'开始。 + 所以!翻转两个数字先!我去。这个是个大坑。 + +2. 乘积product,和移动Carrier都很普通。 + +3. !!最后不能忘了再翻转。 + +4. 最后一个看坑。要是乘积是0,就返回‘0’。 但是这个其实可以在开头catch到没必要做到结尾catch。 + +用到几个StringBuffer的好东西: +reverse(); +sb.deleteCharAt(i) + +找数字,或者26个字母,都可以: +s.charAt(i) - '0'; //数字 +s.charAt(i) - 'a'; //字母 + + +--- +**193. [Next Permutation.java](https://github.com/awangdev/LintCode/blob/master/Java/Next%20Permutation.java)** Level: Medium + +需斟酌。 + +Permutation的规律: +1. 从小的数字开始变化因为都是从小的数字开始recursive遍历。 +2. 正因为1的规律,所以找大的断点数字要从末尾开始: 确保swap过后的permutation依然是 前缀固定时 当下最小的。 + +steps: +1. 找到最后一个上升点,k +2. 从后往前,找到第一个比k大的点, bigIndex +3. swap k && bigIndex +4. 最后反转 (k+1,end) + + + +--- +**194. [Nim Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Nim%20Game.java)** +写一些,发现n=4,5,6,7,8...etc之后的情况有规律性。 +最终很简单n%4!=0就可以了 + +--- +**195. [NQueens.java](https://github.com/awangdev/LintCode/blob/master/Java/NQueens.java)** +index就是col number +值就是row number. + +validate n queue的时候 target row# +1. array 里面不能有 target row# +2. diagnal. 记得公式: + row1 - row2 == col1 - col2. Diagnal elelment.fail + row1 - row2 == -(col1 - col2). Diagnal element. fail + + +--- +**196. [NQueensII.java](https://github.com/awangdev/LintCode/blob/master/Java/NQueensII.java)** +直接add 一个什么乱起八糟的东西进rst都可以。 +然后最后要的是 rst.size() = # of solutons + +--- +**197. [Nth to Last Node in List.java](https://github.com/awangdev/LintCode/blob/master/Java/Nth%20to%20Last%20Node%20in%20List.java)** +然后head开始跑。 + +node 到底,而head ~ node刚好是 n 距离。所以head就是要找的last nth + +--- +**198. [Number of Airplane in the sky.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Airplane%20in%20the%20sky.java)** Level: Medium + +把Interval拆分成数轴上的Point: +起飞mark 1 +降落mark -1 +用PriorityQueue排序, loop through queue, 计算(起飞+降落)值可能有的max。 + +注意: +同时起飞和降落,就是 1 - 1 = 0. 所以在while loop里面有第二个while loop, +当坐标x重合时,在这里做完所有x点的加减,然后再比较 max。 +这避免了错误多count,或者少count + + +--- +**199. [Number of Islands II.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Islands%20II.java)** Level: Hard + +用HashMap的Union-find. + +把board转换成1D array, 就可以用union-find来判断了。 判断时,是在四个方向各走一步,判断是否是同一个Land. + +每走一次operator,都会count++. 若发现是同一个island, count-- + + +--- +**200. [Number of Islands.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20of%20Islands.java)** Level: Medium + +方法1: 两个for loop brutle force。 DFS把每个跟1相关的都Mark一遍.生成一个island. + +方法2: (暂时没有写union-find的解) +可以用union-find, 就像Number of island II 一样。 +只不过这个不Return list, 而只是# of islands + + +--- +**201. [Number Triangles.java](https://github.com/awangdev/LintCode/blob/master/Java/Number%20Triangles.java)** +Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. + +Note +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. + +Example +For example, given the following triangle + +[ + [2], + [3,4], + [6,5,7], + [4,1,8,3] +] +The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11). + +Tags Expand +Dynamic Programming + +Thinking process: +1. Bottom-up + - Start from the bottom row, get all values of this row. Note: in triangle, height = cols at each row. So row X has X numbers. + - Start from (n - 1)th row and run up: calculate min from lower level + current node value. + - Depending what is wanted, here we use a 2D int arraya and return the min sum. +*/ + +public class Solution { + /** + * @param triangle: a list of lists of integers. + * @return: An integer, minimum path sum. + */ + //Bottom - up + public int minimumTotal(ArrayList> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + int n = triangle.size(); + int[][] sum = new int[n][n]; + for (int i = 0; i < n; i++) { + sum[n - 1][i] = triangle.get(n - 1).get(i); + } + for (int i = n - 2; i >= 0; i--) { + for (int j = 0; j <= i; j++) { + sum[i][j] = Math.min(sum[i + 1][j], sum[i + 1][j + 1]) + triangle.get(i).get(j); + } + } + return sum[0][0]; + } +} + +/* +2. Memorize Search + - Go through all nodes and initialize with Integer.MAX_VALUE; + - Search from top: thislevel-current = Math.min(nextlevel-current, nextlevel-next) + thislevel-current + - During the Search Helper, when a node has been set previously, just return this value because this min value has been pre-calculated. + If row is >= triangle.size(), return 0. + - This method can actually calculate the min sum from bottom to any point in the triangle. +*/ + +public class Solution { + /** + * @param triangle: a list of lists of integers. + * @return: An integer, minimum path sum. + */ + + //Version 2 : Memorize Search + private int n; + private ArrayList> triangle; + public int minimumTotal(ArrayList> triangle) { + if (triangle == null || triangle.size() == 0) { + return 0; + } + this.n = triangle.size(); + this.triangle = triangle; + int[][] sum = new int[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j <= i; j++) { + sum[i][j] = Integer.MAX_VALUE; + } + } + return searchHelper(0, 0, sum); + } + + public int searchHelper(int r, int c, int[][] sum) { + if (r >= this.n) { + return 0; + } + if (sum[r][c] != Integer.MAX_VALUE) { + return sum[r][c]; + } + sum[r][c] = Math.min(searchHelper(r + 1, c, sum), searchHelper(r + 1, c + 1, sum)) + this.triangle.get(r).get(c); + return sum[r][c]; + } +} + + + + +--- +**202. [O(1) Check Power of 2.java](https://github.com/awangdev/LintCode/blob/master/Java/O(1)%20Check%20Power%20of%202.java)** +Using O(1) time to check whether an integer n is a power of 2. +Example +For n=4, return true + +For n=5, return false + +Challenge +O(1) time + +Tags Expand +Binary + +Thinking process: +Any integer that's power of 2, follows one pattern. They are all: 1000000000....000 format. +so (n - 1) becomes: 01111111111...111. +If bit-and them togeter, it will be 0. + +*/ + +class Solution { + /* + * @param n: An integer + * @return: True or false + */ + public boolean checkPowerOf2(int n) { + if (n <= 0) { + return false; + } + return (n & (n - 1)) == 0; + } +}; + + + +--- +**203. [One Edit Distance.java](https://github.com/awangdev/LintCode/blob/master/Java/One%20Edit%20Distance.java)** Level: Medium + +理解Edit: 就是删除,增加,和替换。 +换完之后,理论上换成的String 就应该全等 +一旦找到不一样的char, 就判断那三种可能性 + + +--- +**204. [Paint Fence.java](https://github.com/awangdev/LintCode/blob/master/Java/Paint%20Fence.java)** +设定T(n)的做法,最后题目化简以后就跟Fibonacci number一样一样的。详细分析如下。 +做完,还是觉得如有神。本来是个Easy题,想不到,就是搞不出。 + +12.13.2015再看了一下: +因为最多2个fence 颜色相同。 +假设i是和 i-1不同,那么结果就是 (k-1)*dp[i - 1] +假设i是何 i-1相同,那么根据条件,i-1和i-2肯定不同。那么所有的结果就是(k-1)*dp[i-2] +加在一起就有了。 + +--- +**205. [Palindrome Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Linked%20List.java)** +linkedlist不能reverse iterating, 那么就reverse the list, 从中间开花作比较。 + +--- +**206. [Palindrome Partitioning II.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Partitioning%20II.java)** +看上去,在检查i,j的时候,中间按的(i+1, j-1)怎么可能先知道? 其实不然..在j慢慢长大的时候,所有的0~j的substring都检查过。所以isPal[i+1][j-1]一定是已经知道结果的。 + +okay.那么假如以上任意一种情况成立,也就是说isPal[i][j] == true。那就要判断,切到第一层循环参数j的末尾点时,有多少种切法? +想法很顺:我们naturally会想到,把i之前的cut加上i~j之间发生的不就好了。 +反正现在j不变,现在就看吧i定在哪里,cut[i - 1]是否更小/最小; 再在cut[i-1]基础上+1就完了。 + 当然,如果i==0, 而 i~j又是isPal,那没啥好谈的,不必切,0刀。 + +最终,刷到cut[s.length() - 1] 也就是最后一点。 return的理所应当。 + +--- +**207. [Palindrome Partitioning.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Partitioning.java)** +在遍历str的时候,考虑从每个curr spot 到 str 结尾,是能有多少种palindorme? 那就从curr spot当个字符开始算,开始back tracing. +如果所选不是palindrome, 那move on. +若所选的确是palindrome, 加到path里面,DFS去下个level,等遍历到了结尾,这就产生了一种分割成palindrome的串。 +每次DFS结尾,要把这一层加的所选palindrome删掉,backtracking嘛。 + +--- +**208. [Palindrome Permutation II.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Permutation%20II.java)** Level: Medium + +permutation的综合题: +1. validate Input 是不是可以做palindromic permutation. 这个就是(Palindrome Permutation I) +2. 顺便存一下permutation string的前半部分和中间的single character(if any) +3. DFS 做unique permutation: given input有duplicate characters。 + + +--- +**209. [Palindrome Permutation.java](https://github.com/awangdev/LintCode/blob/master/Java/Palindrome%20Permutation.java)** Level: Easy + +注意,条件里面没说是否全是lower case letter + + +--- +**210. [Partition Array by Odd and Even.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20Array%20by%20Odd%20and%20Even.java)** +Partition an integers array into odd number first and even number second. + +Example +Given [1, 2, 3, 4], return [1, 3, 2, 4] + +Challenge +Do it in-place. + +Tags Expand +Two Pointers Array + +Thougths: +Use two pointers: nextOddPt, firstEvenPt +1. Whenever nextOddPt > firstEvenPt, swapt them +2. Incrase nextOddPt in a for loop +Note: +After each swap, have to start checking again from beginning-switching point, which will be firstEvenPt. Need to set i = firstEvenPt. +However, since for loop will do i++, we need to set i = firstEvenPt - 1; +And firstEvenPt only needs to be update once so use -1 to check if it's set. +*/ + +public class Solution { + /** + * @param nums: an array of integers + * @return: nothing + */ + public void partitionArray(int[] nums) { + if (nums == null || nums.length == 0){ + return; + } + int nextOddPt = -1; + int firstEvenPt = -1; + for (int i = 0; i < nums.length; i++) { + if (nums[i] % 2 == 1) { + nextOddPt = i; + } else { + if (firstEvenPt == -1) { + firstEvenPt = i; + } + } + if (nextOddPt > firstEvenPt && firstEvenPt != -1) { + int temp = nums[nextOddPt]; + nums[nextOddPt] = nums[firstEvenPt]; + nums[firstEvenPt] = temp; + i = firstEvenPt - 1; + firstEvenPt = -1; + } + } + } +} + +--- +**211. [Partition Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20Array.java)** +从array两边开始缩进。while loop到遍历完。非常直白的implement。 +注意low/high,或者叫start/end不要越边界 +O(n) + +Quick sort的基础。 + +--- +**212. [Partition List.java](https://github.com/awangdev/LintCode/blob/master/Java/Partition%20List.java)** + +那就最普通的,建造两个list + +把满足条件(=x)的数字分别放到两个list里面 + +记得用dummyNode track head. +最终pre.next = post链接起来。 + +--- +**213. [Pascal's Triangle II.java](https://github.com/awangdev/LintCode/blob/master/Java/Pascal's%20Triangle%20II.java)** Level: Easy + +简单处理array list. + + +--- +**214. [Peeking Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Peeking%20Iterator.java)** + +回到原题,其实不难。找一个cache来存next()的值,然后每次next()里面维护这个cache就好。 + + +--- +**215. [Perfect Squares.java](https://github.com/awangdev/LintCode/blob/master/Java/Perfect%20Squares.java)** + +1. 第一步想到了,从数学角度,可能是从最大的perfect square number开始算起。 +2. 然后想法到了dp, 假设最后一步用了最大的maxSqrNum, 那么就在剩下的 dp[i - maxSqrNum^2] +1 不就好了? +3. 做了,发现有个问题...最后一步选不选maxSqrNum? 比如12就是个例子。 + 然后就根据提示,想到BFS。顺的。 把1~maxSqrNum 都试一试。找个最小的。 + 看我把12拆分的那个example. 那很形象的就是BFS了。 + 面试时候,如果拆分到这个阶段不确定,那跟面试官陶瓷一下,说不定也就提示BFS了。 + +--- +**216. [Permutation Index.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutation%20Index.java)** Level: Easy + +和Permutation Sequence相反的题目。思想类似。 + +题目为Easy,琢磨很久,分析: +每个数位的数字,都是跳过了小于这数字开头的多种可能。 + +举例【6,5,2】吧。我们找6,5,2是permudation里面的第几个。 +正常排序,也就是permutation的第一个,应该是【2,5,6】 +如果要从首位,2,变成6,要跨过多少可能性呢? +很简单,就是问:小于6的数字有多少个呢?(2,5).每个数字变成head,都有各自的一套变化,都有(n-1)!种可能。 + +本题做法:每个(n-1)!加起来。 Note:(n-1) means, 开头的数字(2,5)各带出多少种排列,也就是不就是(n-1)!嘛。 + 这一步,计算数量很简单: (有几个小于6的数字) ×(除去head剩下有多少个数字)! + +以上 ,都是为了把6推上皇位,而牺牲的条数。 + +那么把6推上去以后,还有接下去的呢。 + +接下去要看5,2. +6确定,后面permudation可变的情况有可能是【6,5,2】,那还可能是【6,2,5】呢。 + +Same process, 看given 数组的第二位5,算它接下去: +1. 有几个数字小于5呢? +2. 除去5,还有几个数字可以 factorial呢? +3. 一样的。第一步就结果乘以第二步。 + +最后接下去要看最后一个元素2了。 + + +6,5,2全看过了以后,加起来。 +就是【6,5,2】上位,所踏过的所有小命啊! + +我这解释太生动了。因为耗费了好长时间思考... + + +--- +**217. [Permutation Sequence.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutation%20Sequence.java)** Level: Medium + +k是permutation的一个数位。而permutation是有规律的。 + +也就是说,可以根据k的大小来判断每一个数位的字符(从最大数位开始,因为默认factorio从最大数位开始变化)。 + +于是先求出n!, 然后 k/n!就可以推算出当下这一个数位的字符。然后分别把factorio 和 k减小。 + +另外, 用一个boolean[] visited来确保每个数字只出现一次。 + +这个方法比计算出每个permutation要efficient许多。 + + + +--- +**218. [Permutations II.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutations%20II.java)** Level: Medium + +方法1: +Mark visited. 并且要检查上一层recursive时有没有略过重复element. 并且要排序,通过permutation规律查看是否排出了重复结果。 + +背景1:在recursive call里面有for loop, 每次从i=0开始, 试着在当下list上加上nums里面的每一个。 +从i=0开始,所以会依次recursive每一个nums:因此,例如i=2,肯定比i=3先被访问。也就是:取i=2的那个list permutation肯定先排出来。 + +背景2:重复的例子:给出Input[x, y1, y2], 假设y的值是一样的。那么,{x,y1,y2}和{x,y2,y1}是相同结果。 + +综上,y1肯定比y2先被访问,{x,y1,y2}先出。 紧随其后,在另一个recursive循环里,{x,y2...}y2被先访问,跳过了y1。 +重点:规律在此,如果跳过y1,也就是visited[y1] == false, 而num[y2] == num[y1],那么这就是一个重复的结果,没必要做,越过。 + +结果:那么,我们需要input像{x,y1,y2}这样数值放一起,那么必须排序。 + + +方法2: +一个办法就是给一个visited queue。 和queue在所有的地方一同populate. 然后visited里面存得时visited indexes。 (Not efficient code. check again) + + +--- +**219. [Permutations.java](https://github.com/awangdev/LintCode/blob/master/Java/Permutations.java)** Level: Medium + +Recursive: 取,或者不取。 + +Iterative: 用个queue,每次poll()出来的list, 把在nums里面能加的挨个加一遍。 However, code is a bit massive. + + + +--- +**220. [Plus One.java](https://github.com/awangdev/LintCode/blob/master/Java/Plus%20One.java)** +Given a non-negative number represented as an array of digits, plus one to the number. + +The digits are stored such that the most significant digit is at the head of the list. + + +Example +Given [1,2,3] which represents 123, return [1,2,4]. + +Given [9,9,9] which represents 999, return [1,0,0,0]. + +Tags Expand +Array + +*/ + +public class Solution { + public int[] plusOne(int[] digits) { + if(digits.length==0) return digits; + + digits[digits.length-1] += 1; + //Check index digit.length-1 to 1 + for(int i = digits.length-1; i>0; i--){ + if(digits[i] == 10){ + digits[i]=0; + digits[i-1]+=1; + } + else return digits; + } + + //Check index 0. If ==0, set it to 0 and carry over 1 + if(digits[0]==10){ + int[] output = new int[digits.length+1]; + output[0] = 1; + output[1] = 0; + for(int i=2; i productExcludeItself(ArrayList A) { + if (A == null || A.size() == 0) { + return null; + } + ArrayList rst = new ArrayList(); + for (int i = 0; i < A.size(); i++) { + long num = 1; + for (int j = 0; j < A.size(); j++) { + if (j != i) { + num *= A.get(j); + } + } + rst.add(num); + } + return rst; + } +} + + + +--- +**226. [QuickSort.java](https://github.com/awangdev/LintCode/blob/master/Java/QuickSort.java)** Level: Easy + +代码是不难的. + +首先partition. 返还一个partition的那个中间点的位置。 +然后劈开两半。 +前后各自 quick sort, recursively + +注意:在partition里面, 比较的时候nums[start] < pivot, nums[end]>pivot, 如果写成了 <= 会 stack overflow. + + +但是: 在partition array那个题目里面,第二个 nums[end] >= pivot, 是要去加上这个 ‘=’的 + + +--- +**227. [Recover Rotated Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Recover%20Rotated%20Sorted%20Array.java)** +Rotate三步: +rotate前半 +rotate后半 +rotate全部 + +注意先找到断点。 + +--- +**228. [Rehashing.java](https://github.com/awangdev/LintCode/blob/master/Java/Rehashing.java)** Level: Medium + + + +--- +**229. [Remove Duplicates from Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20Array.java)** + +LinkedList里面我们是最好不要动node.val的,直接把node去掉。 +而array我们很难直接把node去掉,又不能用新array,那么就要: + +把不重复的element一个个放到最前面。 + + +这个思想跟merge two sorted array (其中一个后续非常长的array可以放下arr1,arr2) 类似。 +就是找个不会事后mess up,不会去动得index,把满足条件的element 填进去。这样保证了in place. + +* 有个反向思维:remove duplicate,实际上也是找unique elements, and insert into original array + + +--- +**230. [Remove Duplicates from Sorted List II.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20List%20II.java)** +多个node,check node.next ?= node.next.next + +--- +**231. [Remove Duplicates from Sorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Sorted%20List.java)** + +--- +**232. [Remove Duplicates from Unsorted List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Duplicates%20from%20Unsorted%20List.java)** +遍历。 +遇到duplicate(可能多个), while直到node.next不是duplicate. +接下去,既然不是duplicate,那就add 进 set + + +如果不用extra memory, do it in place: +那就要sort linked list. 用merge sort. + +复习merge sort: +1. find middle. +2. recursively: right = sort(mid.next); left = sort(head). +3. within sort(), at the end call merge(left, right) + +--- +**233. [Remove Linked List Elements.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Linked%20List%20Elements.java)** +如果不match, parent 和 node 一起移动 + +--- +**234. [Remove Node in Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Node%20in%20Binary%20Search%20Tree.java)** Level: Hard + +方法1: Brutle一点。找到target和target的parent. +把target remove时,把target的children nodes 重新排列组成新的BST: inorder traversal, build tree based on inorder traversal list. + +方法2: 分析规律,先找到target和parent, 然后根据性质,把target remove时,移动children nodes, 保证还是BST。 + + +--- +**235. [Remove Nth Node From End of List.java](https://github.com/awangdev/LintCode/blob/master/Java/Remove%20Nth%20Node%20From%20End%20of%20List.java)** +Given a linked list, remove the nth node from the end of list and return its head. + +Note +The minimum number of nodes in list is n. + +Example +Given linked list: 1->2->3->4->5->null, and n = 2. +After removing the second node from the end, the linked list becomes 1->2->3->5->null. +Challenge +O(n) time + +Tags Expand +Two Pointers Linked List + +Thinking process: +Very similar to 'Nth to last node'. Except, have a pre pointer to keep track of the previous node of 'nth to last'. +Also have a dummy.next to store the beginning of the list; +*/ +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + /** + * @param head: The first node of linked list. + * @param n: An integer. + * @return: The head of linked list. + */ + ListNode removeNthFromEnd(ListNode head, int n) { + if (head == null || n < 0) { + return null; + } + int count = 0; + ListNode dummy = new ListNode(0); + ListNode pre = new ListNode(0); + pre.next = head; + dummy = pre; + ListNode node = head; + while (node != null && count < n) { + node = node.next; + count++; + } + while (node != null) { + node = node.next; + head = head.next; + pre = pre.next; + } + pre.next = head.next; + return dummy.next; + } +} + + + + +--- +**236. [Reorder List.java](https://github.com/awangdev/LintCode/blob/master/Java/Reorder%20List.java)** +24% 通过 +Given a singly linked list L: L0→L1→…→Ln-1→Ln, +reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… + +You must do this in-place without altering the nodes' values. + + + +样例 +For example, +Given 1->2->3->4->null, reorder it to 1->4->2->3->null. + +标签 Expand +Linked List + +Thinking Process: +Similar to sort list: +find middle. +reverse last section +merge(head, mid) alternatively by using index % 2. +Append whatever left from the 2 lists +Note: re-order in place, does not necessarily mean you can create any variable. As long as the variable is O(1), it should be fine. +*/ + +/** + * Definition for ListNode. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int val) { + * this.val = val; + * this.next = null; + * } + * } + */ +public class Solution { + private ListNode reverse(ListNode head) { + ListNode reversedList = null; + while (head != null) { + ListNode temp = head.next; + head.next = reversedList; + reversedList = head; + head = temp; + } + return reversedList; + } + + private void merge(ListNode head1, ListNode head2) { + ListNode dummy = new ListNode(0); + int index = 0; + while (head1 != null && head2 != null) { + if (index % 2 == 0) { + dummy.next = head1; + head1 = head1.next; + } else { + dummy.next = head2; + head2 = head2.next; + } + dummy = dummy.next; + index += 1; + } + if (head1 != null) { + dummy.next = head1; + } else if (head2 != null) { + dummy.next = head2; + } + } + + private ListNode findMiddle(ListNode head) { + ListNode slow = head; + ListNode fast = head.next; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + + public void reorderList(ListNode head) { + if (head == null || head.next == null) { + return; + } + + ListNode mid = findMiddle(head); + ListNode tail = reverse(mid.next); + mid.next = null; + + merge(head, tail); + } +} + + +--- +**237. [Restore IP Addresses.java](https://github.com/awangdev/LintCode/blob/master/Java/Restore%20IP%20Addresses.java)** +递归在一个index上面(具体问题,具体分析的情况) +validate string要注意leading '0' + +注意: 递归的时候可以用一个start/level/index来跑路 +但是尽量不要去改变Input source, 会变得非常confusing. + + +--- +**238. [Reverse Integer.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Integer.java)** +Reverse digits of an integer. Returns 0 when the reversed integer overflows (signed 32-bit integer). + +Example +Given x = 123, return 321 + +Given x = -123, return -321 + +Tags Expand +Integer + +Thoughts: +1. Use long to capture the result. If > Integer.MAX_VALUE,return 0; +2. Use string to reverse, the conver to long +3. use string builder to reverse string + +*/ + + +public class Solution { + /** + * @param n the integer to be reversed + * @return the reversed integer + */ + public int reverseInteger(int n) { + long num = (long)n; + int sign = n > 0 ? 1 : -1; + String rst = new StringBuilder(Math.abs(num)+"").reverse().toString(); + num = Long.parseLong(rst) * sign; + + if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE) { + return 0; + } else { + return (int)num; + } + } +} + +--- +**239. [Reverse Linked List II .java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Linked%20List%20II%20.java)** +存一下那个点, +从M开始, for loop, reverse [m~n]。 然后把三段链接在一起。 + + + +--- +**240. [Reverse Linked List.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Linked%20List.java)** Level: Easy + +建立新list。每次把newList append 在current node的后面。 +用head来循环所有node。 + + +--- +**241. [Reverse Words in a String II.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Words%20in%20a%20String%20II.java)** Level: Medium + +In-place reverse. + +reverse用两回. 全局reverse。局部:遇到空格reverse。 + +注意:结尾点即使没有' '也要给reverse一下最后一个词。 + + + +--- +**242. [Reverse Words in a String.java](https://github.com/awangdev/LintCode/blob/master/Java/Reverse%20Words%20in%20a%20String.java)** Level: Medium + +几种不同的方法flip: +坑: 1. 结尾不能有空格。 2. 注意,如果Input是 ‘ ’的话,split以后就啥也没有了。check split以后 length == 0 + +另个题目Reverse Words in String (char[]) 可以in-place,因为条件说char[]里面是没有首尾空格,好做许多哟. + + +--- +**243. [reverseInteger.java](https://github.com/awangdev/LintCode/blob/master/Java/reverseInteger.java)** +Reverse Integer + +Reverse digits of an integer. + +Example1: x = 123, return 321 +Example2: x = -123, return -321 +//input = 1534236469 + +Thinking process: +Make sure of operators. +Note: check for overflow using long. When integer is > Integer.MAX_VALUE, then it's overflow. +Initialize long : long x = 1234L; +Convert using (int) + +*/ +public class Solution { + public int reverse(int x) { + if (x == 0) { + return x; //123 + } + boolean sign = x > 0; //sign = true + long rst = 0L; + x = Math.abs(x); // 123 + while (x != 0) { //x = 123, 12, 1 + rst = rst * 10 + x % 10; //rst = 3, 30 + 2 = 32, 320 + 1 = 321 + x = x / 10; //x = 12; 1; 0 + } + if (rst < 0 || rst > Integer.MAX_VALUE) { + return 0; + } + return sign ? (int)rst : -(int)rst; + } +} + + +--- +**244. [Roman to Integer.java](https://github.com/awangdev/LintCode/blob/master/Java/Roman%20to%20Integer.java)** Level: Easy + +熟悉罗马字母规则 +1. 'I V X L C D M' 分别代表的数字 +2. 'IV, IX'减1, 'XL, XC'减10, 'CD, CM'减100. + + +--- +**245. [Rotate Image.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20Image.java)** Level: Medium + +找到个转角度的规律公式。用一个temp。in place. + + +--- +**246. [Rotate List.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20List.java)** +/* Given a list, rotate the list to the right by k places, where k is non-negative. + +Example +Given 1->2->3->4->5->null and k=2 +return 4->5->1->2->3->null +Tags Expand +Basic Implementation Linked List + +Thining process: +Two pointers. +First pointer move k steps. +Then 2 pointers start moving together. When 1st pointer reaches the end, then 2nd pointer should be in middle. +Let 2nd pointer be head, and move original head to tail of the list + +*/ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param head: the List + * @param k: rotate to the right k places + * @return: the list after rotation + */ + public ListNode rotateRight(ListNode head, int k) { + if (head == null || k == 0) { + return head; + } + //Check length + int length = 0; + ListNode dummy = head; + while(dummy != null) { + dummy = dummy.next; + length++; + } + k = k % length; + //Store dummy as 1 node before tail + dummy = new ListNode(0); + dummy.next = head; + head = dummy; + for (int i = 0; i < k; i++) { + head = head.next; + } + //Move 2 pointers. When head reaches end, tail.next will be at the newHead + ListNode tail = dummy; + while (head.next != null) { + head = head.next; + tail = tail.next; + } + head.next = dummy.next;//Link old Head to the end, form circle + dummy.next = tail.next;//Link tail.next as new head. tail should be end point. + tail.next = null;//add null to end point tail + return dummy.next; + } +} + +--- +**247. [Rotate String.java](https://github.com/awangdev/LintCode/blob/master/Java/Rotate%20String.java)** +有个坑:offset可能很长,那么要%length,才能得到真正需要rotate的部分。 +Note: rotate 一个 full length之后,是string 不变 + +--- +**248. [Search a 2D Matrix II.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20a%202D%20Matrix%20II.java)** +每次删掉一行,或者一列 + +--- +**249. [Search a 2D Matrix.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20a%202D%20Matrix.java)** +2D转1D。 +Binary Search + +--- +**250. [Search for a Range.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20for%20a%20Range.java)** + +--- +**251. [Search Insert Position.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Insert%20Position.java)** +在结尾判断该return 哪个position。 + +--- +**252. [Search Range in Binary Search Tree .java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Range%20in%20Binary%20Search%20Tree%20.java)** Level: Medium + +等于遍历了所有k1<= x <= k2的x node。 + +如果是用Binary Search Tree搜索,那么一般是if (...) else {...},也就是一条路走到底,直到找到target. + +这里, 把 left/right/match的情况全部cover了,然后把k1,k2的边框限制好,中间就全部遍历了。 + + +--- +**253. [Search Rotated in Sorted Array II.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Rotated%20in%20Sorted%20Array%20II.java)** +因为最终binary search的结果也是O(n) +所以这道题要记得: 既然是O(n), 那来个简单的for loop 也就好了。 + +当然,要跟面试官提起来原因。别一上来就只有for。。。 + +--- +**254. [Search Rotated in Sorted Array.java](https://github.com/awangdev/LintCode/blob/master/Java/Search%20Rotated%20in%20Sorted%20Array.java)** Level: Hard + +方法1:O(logn) + 还是把它先当做正常的sorted list开始搜。 + 但是在比较的时候,多比较一个A[start] < A[mid]? + 在1 和 2 里面分别讨论 target 的位置 + 1. A[start] < A[mid] ? + 说明在前半段 + - start mid + 2. A[start] > A[mid] + 说明 start 还在前半段,而mid在后半段 + - mid < target < end + - target < mid + + + +方法2:O(logn) + 1. binay search break point + 2. binary search target + 注意等号,在判断target在前半段还是后半段:if (A[p1] <= target && target <= A[breakPoint]) + + + + +--- +**255. [Segment Tree Build II.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Build%20II.java)** Level: Medium + + +给的是Array。注意找区间内的max, assign给区间。 其余和普通的segment tree build一样 + +给了array,但是并不根据array里的内容排位,而是依然根据index in [0, array.length - 1]割开区间,break到底, +最终start==end。同时assign max=A[start] or A[end] + +往上,parent一层的max:就是比较左右孩子,其实都是在两个sub-tree里面比较sub-tree的max。 + +这就好做了: +先分,找到left/right,比较max,在create current node,再append到当前node上面。 + +实际上是depth-first, 自底向上建立起的。 + + +--- +**256. [Segment Tree Build.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Build.java)** Level: Medium + +按定义: +左孩子:(A.left, (A.left+A.rigth)/2) +右孩子:((A.left+A.rigth)/2+1, A.right) + + +--- +**257. [Segment Tree Modify.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Modify.java)** Level: Medium + +Recursively 在segment tree里面找index, update it with value. + +每个iteration,很可能(要么左手,要么右手)max就变了。所以每次都left.max and right.max compare一下。 +最后轮回到头顶,头顶一下包括头顶,就全部都是max了。 + +Divde and Conquer + + +--- +**258. [Segment Tree Query II.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Query%20II.java)** Level: Medium + +和 Segment Tree Query I 以及其他Segment Tree问题没啥区别。这个就是return个count。 + +这个题目考了validate input source:input 的start,end可能超出root[start,end]。 +那么第一步就要先clear一下。完全不在range就return 0. 有range重合就规整到root的range. + + + + +--- +**259. [Segment Tree Query.java](https://github.com/awangdev/LintCode/blob/master/Java/Segment%20Tree%20Query.java)** Level: Medium + +给了segment Tree, node里面有Max value, 找[start,end]里面的max + +[start,end]跟mid相比,可能: +全在mid左 +全在mid右 +包含了mid: 这里要特别break into 2 query method + +按定义: +mid = (root.start + root.end)/2 + + +--- +**260. [Serilization and Deserialization Of Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Serilization%20and%20Deserialization%20Of%20Binary%20Tree.java)** +Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called 'serialization' and reading back from the file to reconstruct the exact same binary tree is 'deserialization'. + +There is no limit of how you deserialize or serialize a binary tree, you only need to make sure you can serialize a binary tree to a string and deserialize this string to the original structure. + +Example +An example of testdata: Binary tree {3,9,20,#,#,15,7}, denote the following structure: + + 3 + / \ + 9 20 + / \ + 15 7 +Our data serialization use bfs traversal. This is just for when you got wrong answer and want to debug the input. + +You can use other method to do serializaiton and deserialization. + +Tags Expand +Binary Tree + +Thinking process: +1. Carefully turn the binary tree into a string: use pre-order in this example. +2. Use a global variable to track the data(data string will be cut in different levels of recursion). +The concept is very easy tho, just need to carefully code it up. + +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +class Solution { + /** + * This method will be invoked first, you should design your own algorithm + * to serialize a binary tree which denote by a root node to a string which + * can be easily deserialized by your own "deserialize" method later. + */ + public String serialize(TreeNode root) { + if (root == null) { + return "#,"; + } + String mid = root.val + ","; + String left = serialize(root.left); + String right = serialize(root.right); + mid += left + right; + return mid; + } + + private String data = ""; + /** + * This method will be invoked second, the argument data is what exactly + * you serialized at method "serialize", that means the data is not given by + * system, it's given by your own serialize method. So the format of data is + * designed by yourself, and deserialize it here as you serialize it in + * "serialize" method. + */ + public TreeNode deserialize(String data) { + this.data = data; + return desHelper(); + } + + public TreeNode desHelper() { + if (this.data.indexOf("#,") == 0) { + this.data = this.data.substring(this.data.indexOf(",") + 1); + return null; + } + String midVal = this.data.substring(0, this.data.indexOf(",")); + TreeNode mid = new TreeNode(Integer.parseInt(midVal)); + this.data = this.data.substring(this.data.indexOf(",") + 1); + TreeNode left = desHelper(); + TreeNode right = desHelper(); + mid.left = left; + mid.right = right; + return mid; + } +} + + + + +--- +**261. [Single Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number%20II.java)** +Given 3*n + 1 numbers, every numbers occurs triple times except one, find it. +Example +Given [1,1,2,3,3,3,2,2,4,1] return 4 + +Challenge +One-pass, constant extra space +Thinking process: +Still using bit manipulation. We need to erase all of the 3-appearance number and leave the single number out. A few steps: +Store the final result by continuously bit OR with the result variable. +Want to XOR the 3 numbers, but can’t erase them as if only 2 duplicate numbers:Consider the number as 3-based number, so XOR can be understand this way + when add 3 numbers together, add each individual bit. If the sum is 3, then set it as 0. If not 3, leave as is. +3. Store the bits in a integer array, which simulates a binary version of the integer +4. When each bit’s XOR process finishes, bit OR it with result +*/ + +public class Solution { + public int singleNumberII(int[] A) { + if (A == null || A.length == 0) { + return -1; + } + //present the XOR results in binary format + int[] bits = new int[32]; + int rst = 0; + for (int i = 0; i < 32; i++) { + for (int j = 0; j < A.length; j++){ + //XOR the numbers in a 3-base fashion. Whenever bit[i] has a number 3, set it back to 0. + bits[i] += A[j] >> i & 1; + bits[i] %= 3; + } + //OR it to the result. However, each time only the i - spot is updated with the bits[i]. + rst |= bits[i] << i; + } + return rst; + } +} + + +--- +**262. [Single Number III.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number%20III.java)** +Given 2*n + 2 numbers, every numbers occurs twice except two, find them. + +Example +Given [1,2,2,3,4,4,5,3] return 1 and 5 + +Challenge +O(n) time, O(1) extra space. + +Thinking Process: +The 2 exception must have this feature: a ^ b != 0, since they are different +Still want to do 2n + 1 problem as in Single Number I, then we need to split a and b into 2 groups and deal with two 2n+1 problems +Assume c = a^b, there mush be a bit where a and b has the difference, so that bit in c is 1. +Find this bit position and use it to split the group: shift number in the array by ‘bit-position’ indexes. If the shifted number has 1 at the ‘bit-position’, set it to one group; otherwise to another group. +*/ + +public class Solution { + /** + * @param A : An integer array + * @return : Two integers + */ + public List singleNumberIII(int[] A) { + if (A == null || A.length == 0) { + return null; + } + List rst = new ArrayList(); + int xor = 0; + for (int i = 0; i < A.length; i++) { + xor ^= A[i]; + } + int bitOnePos = 0; + for (int i = 0; i < 32; i++) { + if ((xor >> i & 1) == 1) { + bitOnePos = i; + } + } + int rstA = 0; + int rstB = 0; + for (int i = 0; i < A.length; i++) { + if ((A[i] >> bitOnePos & 1) == 1) { + rstA ^= A[i]; + } else { + rstB ^= A[i]; + } + } + rst.add(rstA); + rst.add(rstB); + return rst; + } +} + + +--- +**263. [Single Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Single%20Number.java)** +62% Accepted +Given 2*n + 1 numbers, every numbers occurs twice except one, find it. + +Example +Given [1,2,2,1,3,4,3], return 4 + +Challenge +One-pass, constant extra space + +Tags Expand +Greedy + +Manipulate bits: +Thinking process: +One-pass and constant extra space. +since all numbers appears twice, consider them as in bits format. Two identical number XOR will be zero. If we XOR everything double-numbers together, it will be zero. At the end, we use o XOR our target number, the result is actually the target number. +Very smart trick to use bits. +In order to compare from index 0 to the end, we need to extract index 0 first as result before for loop. And start for loop at i = 1. +*/ + +public class Solution { + /** + *@param A : an integer array + *return : a integer + */ + public int singleNumber(int[] A) { + if (A == null || A.length == 0) { + return 0; + } + int rst = A[0]; + for (int i = 1; i < A.length; i++) { + rst = rst ^ A[i]; + } + return rst; + } +} + + + + +--- +**264. [Singleton.java](https://github.com/awangdev/LintCode/blob/master/Java/Singleton.java)** +Singleton is a most widely used design pattern. If a class has and only has one instance at every moment, we call this design as singleton. For example, for class Mouse (not a animal mouse), we should design it in singleton. + +You job is to implement a getInstance method for given class, return the same instance of this class every time you call this method. + + +Example +In Java: + +A a = A.getInstance(); +A b = A.getInstance(); +a should equal to b. + +Challenge +If we call getInstance concurrently, can you make sure your code could run correctly? + +Tags Expand +LintCode Copyright OO Design + +Thoughts: +... +Was not clear to me. Need to loop up more on synchronized/volatile +Good reference: +http://www.cnblogs.com/EdwardLiu/p/4443230.html + +*/ + + +class Solution { + public static volatile Solution solution = null; + /** + * @return: The same instance of this class every time + */ + public static Solution getInstance() { + if (solution == null) { + synchronized (Solution.class) { + // Double check + if (solution == null) { + solution = new Solution(); + } + } + } + return solution; + } +}; + +--- +**265. [Sliding Window Maximum.java](https://github.com/awangdev/LintCode/blob/master/Java/Sliding%20Window%20Maximum.java)** +每次把小于当前node的,全部剔除,剩下的,自然就是:最大的>第二大的>第三大的...ETC. +为啥可以不管不无地剔除? +因为我们只在乎最大值的存在;而任何小于当前(正要新就加进去的)值的,反正以后也成不了最大值,于是扔掉! + +--- +**266. [Sliding Window Median.java](https://github.com/awangdev/LintCode/blob/master/Java/Sliding%20Window%20Median.java)** +移动窗口2step: +1. 加一个数。 +2. 减一个数。 +加减时看好,是从前面的maxheap里面抽,还是从后面的minHeap里面抽。 +抽完balance一下。 + +记得: +左边的maxHeap总有 x+1或者x个数字。 +后边minHeap应该一直有x个数字。 + + +--- +**267. [Sort Color.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Color.java)** +Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. + +Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. + +Example +Note +You are not suppose to use the library's sort function for this problem. + +Clarification +Follow up: +A rather straight forward solution is a two-pass algorithm using counting sort. +First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. + +Could you come up with an one-pass algorithm using only constant space? + +Tags Expand +Two Pointers Sort Array + +Thoughts; +A easier version of Sort ColorII. Using the exact same code with different k number. Note, now k is start from 0. + +*/ + +class Solution { + /** + * @param nums: A list of integer which is 0, 1 or 2 + * @return: nothing + */ + public void sortColors(int[] colors) { + if (colors == null || colors.length == 0) { + return; + } + int end = colors.length - 1; + int k = 2; // 3 different colors + for (int i = 0; i < k; i++) { + end = helper(colors, 0, end, k - i - 1); + } + } + + public void swap(int[] colors, int x, int y){ + int temp = colors[x]; + colors[x] = colors[y]; + colors[y] = temp; + } + + public int helper(int[] colors, int start, int end, int pivot) { + int low = start; + int high = end; + while (low <= high) { + while(low < high && colors[low] <= pivot) { + low++; + } + while(high > 0 && colors[high] > pivot) { + high--; + } + if (low <= high) { + swap(colors, low, high); + low++; + high--; + } + } + return low - 1; + } +} + + + + + + + + + + + + + + + + + + +--- +**268. [Sort Colors II.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Colors%20II.java)** +Given an array of n objects with k different colors (numbered from 1 to k), sort them so that objects of the same color are adjacent, with the colors in the order 1, 2, ... k. + +Example +GIven colors=[3, 2, 2, 1, 4], k=4, your code should sort colors in-place to [1, 2, 2, 3, 4]. + +Note +You are not suppose to use the library's sort function for this problem. + +Challenge +A rather straight forward solution is a two-pass algorithm using counting sort. That will cost O(k) extra memory. + +Can you do it without using extra memory? + +Tags Expand +Two Pointers Sort + +Thoughts (Need to revist and think about this, very interesting) +Doing quick sort partition for K -1 times. +1. Use K - 1 value as pivot +2. Starting from 0, whenever low0, and greater than pivot, high-- +4. Result: only swap when low and high have disagreement on the pivot value. + +*/ + +class Solution { + /** + * @param colors: A list of integer + * @param k: An integer + * @return: nothing + */ + public void sortColors2(int[] colors, int k) { + if (colors == null || colors.length == 0 || k <= 0) { + return; + } + int end = colors.length - 1; + for (int i = 0; i < k - 1; i++) { + end = helper(colors, 0, end, k - i - 1); + } + } + + public void swap(int[] colors, int x, int y){ + int temp = colors[x]; + colors[x] = colors[y]; + colors[y] = temp; + } + + public int helper(int[] colors, int start, int end, int pivot) { + int low = start; + int high = end; + while (low <= high) { + while(low < high && colors[low] <= pivot) { + low++; + } + while(high > 0 && colors[high] > pivot) { + high--; + } + if (low <= high) { + swap(colors, low, high); + low++; + high--; + } + } + return low - 1; + } +} + + + + + + + + + + + + + + + + + + +--- +**269. [Sort Letters by Case.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20Letters%20by%20Case.java)** +Given a string which contains only letters. Sort it by lower case first and upper case second. + +Example +For "abAcD", a reasonable answer is "acbAD" + +Note +It's not necessary to keep the original order of lower-case letters and upper case letters. + +Challenge +Do it in one-pass and in-place. + +Tags Expand +String Two Pointers LintCode Copyright Sort + +Thoughts: +Another two pointer sorting. +Difference: use a ASCII code 'a' as the pivot. all the letters that from a ~ z +have bigger integer values, and A~Z have small integer values. +This problem requires lowcase+upperCase, so we'd sort the list from high to low. +NOTE: in the 2 while loop, the it's always having ">=' + +*/ + + +public class Solution { + /** + *@param chars: The letter array you should sort by Case + *@return: void + */ + public void sortLetters(char[] chars) { + if (chars == null || chars.length == 0) { + return; + } + char pivot = 'a'; + int start = 0; int end = chars.length - 1; + while (start <= end) { + while (start <= end && chars[start] >= pivot) { + start++; + } + while (start <= end && chars[end] < pivot) { + end--; + } + if (start <= end) { + char temp = chars[end]; + chars[end] = chars[start]; + chars[start] = temp; + start++; + end--; + } + } + } +} + + + + + + + + + + + + +--- +**270. [Sort List.java](https://github.com/awangdev/LintCode/blob/master/Java/Sort%20List.java)** + 1. find middle. 快慢指针 + 2. Merge: 假设given list A, B 已经是sorted, 然后按照大小,混合。 + 3. Sort: 切开两半,先sort前半, 如果先sort了mid.next~end, sort后,中间点mid.next == null,再sort前半段。 + 然后mege. + 要recursively call itself. + +Quick sort: +想做可以看讲义:http://www.jiuzhang.com/solutions/sort-list/ + +但是quick sort不建议用在list上面。 + +排列list, merge sort可能更可行和合理。原因分析在下面, 以及: http://www.geeksforgeeks.org/why-quick-sort-preferred-for-arrays-and-merge-sort-for-linked-lists/ + + +--- +**271. [Space Replacement.java](https://github.com/awangdev/LintCode/blob/master/Java/Space%20Replacement.java)** +Write a method to replace all spaces in a string with %20. The string is given in a characters array, you can assume it has enough space for replacement and you are given the true length of the string. + +Example +Given "Mr John Smith", length = 13. + +The string after replacement should be "Mr%20John%20Smith". + +Note +If you are using Java or Python,please use characters array instead of string. + +Challenge +Do it in-place. + +Tags Expand +String Cracking The Coding Interview + +Thoughts: +Overriding the array from the back to front. +This is because as we re-writing the string from the back, stuff at head of the string does not change yet. +This is wonderful:) + +*/ + + +public class Solution { + /** + * @param string: An array of Char + * @param length: The true length of the string + * @return: The true length of new string + */ + public int replaceBlank(char[] string, int length) { + if (string == null || string.length == 0) { + return 0; + } + int count = 0; + for (char c : string) { + if (c == ' ') { + count += 2; + } + } + int lastIndex = length + count - 1; + //from back to front: + for (int i = length - 1; i >= 0; i--) { + if (string[i] == ' ') { + string[lastIndex--] = '0'; + string[lastIndex--] = '2'; + string[lastIndex--] = '%'; + } else { + string[lastIndex--] = string[i]; + } + } + return length + count; + } +} + +--- +**272. [Sqrt(x).java](https://github.com/awangdev/LintCode/blob/master/Java/Sqrt(x).java)** +Implement int sqrt(int x). + +Compute and return the square root of x. + +Example +sqrt(3) = 1 + +sqrt(4) = 2 + +sqrt(5) = 2 + +sqrt(10) = 3 +Challenge +O(log(x)) + +Tags Expand +Binary Search + +Thinking process: +Binary search. While loop until the head and tail meets. +*/ + +class Solution { + /** + * @param x: An integer + * @return: The sqrt of x + */ + public int sqrt(int x) { + long start = 0; + long end = x; + while (end >= start) { + long mid = start + (end - start) / 2; + if (mid * mid > x) { + end = mid - 1; + } else if (mid * mid < x) { + start = mid + 1; + } else { + return (int)mid; + } + } + //When start > end, while loop ends. That means, end must be the largest possible integer that end^2 is closest to x. + return (int)end; + } +} + +--- +**273. [Stone Game.java](https://github.com/awangdev/LintCode/blob/master/Java/Stone%20Game.java)** +NOT DONE YET + +--- +**274. [String to Integer(atoi).java](https://github.com/awangdev/LintCode/blob/master/Java/String%20to%20Integer(atoi).java)** Level: Easy + +方法1: 问清情况,一点一点把case都涉及到。 + +方法2: 用regular expression。if (!str.matches("[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)")). 猛了一点 + + +--- +**275. [Strobogrammatic Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Strobogrammatic%20Number%20II.java)** +难的case先不handle.到底之后来一次O(n) scan. +总共的时间起码是O(n/2) + O(n), 所以还是O(n) + +--- +**276. [Strobogrammatic Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Strobogrammatic%20Number.java)** +A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down). +Write a function to determine if a number is strobogrammatic. The number is represented as a string. +For example, the numbers "69", "88", and "818" are all strobogrammatic. +Tags: Hash Table Math +Similar Problems: (M) Strobogrammatic Number II, (H) Strobogrammatic Number III +*/ + +/* +OPTS 11.04.2015 +Thoughts: +Because the symmetric pairs are: +1-1, 8-8,0-0,6-9,9-6, we make a hashmap of it. +Create left/right pointer, where each compare has to match the pair in hashmap. + +Note: +On map.containsKey() line, need to check (right), or whichever item that map is going to map.get(...) afterwards. +If containsKey fails, return false; only when it passes through, then proceed to mpa.get() +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + HashMap map = new HashMap(); + map.put('0','0'); + map.put('1','1'); + map.put('8','8'); + map.put('6','9'); + map.put('9','6'); + int left = 0; + int right = num.length() - 1; + while (left <= right) { + if (!map.containsKey(num.charAt(right)) || num.charAt(left) != map.get(num.charAt(right))) { + return false; + } + left++; + right--; + } + return true; + } +} + +/* +Thoughts: +Compare digits to the symmetric postion; special care for (6,9) pair, mark it after comparision. +Elimite the cases before the for-loop run through(can do it in or as well, but that just make the code a bit complex) +Note: +Didn't use HashMap. I beleive hash map is used to mark the spot? +*/ +public class Solution { + public boolean isStrobogrammatic(String num) { + if (num == null || num.length() == 0) { + return true; + } + //Any non-strobogrammatic + if (num.indexOf("2") >= 0 || num.indexOf("3") >= 0 || + num.indexOf("4") >= 0 || num.indexOf("5") >= 0 || + num.indexOf("7") >= 0) { + return false; + } + //If only 6 or 9 exist: + if ((num.indexOf("6") >= 0 && num.indexOf("9") < 0) || + (num.indexOf("9") >= 0 && num.indexOf("6") < 0)) { + return false; + } + //Check if (6,9) or other strobogrammatic # are appearing at symmetric position + char[] arr = num.toCharArray(); + int leng = num.length(); + for (int i = 0; i < leng; i++) { + if (arr[i] == '6' || arr[i] == '9') { + if ((arr[i] == '6' && arr[leng - i - 1] != '9') || + (arr[i] == '9' && arr[leng - i - 1] != '6')) { + return false; + } + arr[i] = arr[leng - i - 1] = 'M';//marker + } else if (arr[i] != 'M' && arr[i] != arr[leng - i - 1]) { + return false; + } + } + return true; + } +} + +--- +**277. [StrStr.java](https://github.com/awangdev/LintCode/blob/master/Java/StrStr.java)** +StrStr: +strStr My Submissions + +19% Accepted +strstr (a.k.a find sub string), is a useful function in string operation. You task is to implement this function. + +For a given source string and a target string, you should output the "first" index(from 0) of target string in source string. + +If target is not exist in source, just return -1. + +Example +If source="source" and target="target", return -1. + +If source="abcdabcdefg" and target="bcd", return 1. + +Challenge +O(n) time. + +Clarification +Do I need to implement KMP Algorithm in an interview? + + - Not necessary. When this problem occurs in an interview, the interviewer just want to test your basic implementation ability. + +Tags Expand +Basic Implementation String + +Thinking process: +Two Pointer. +String Null case. +Break Statement. + + +Check position i+j of source and position j of target. If not match, break out. +If j matches target.length(), means target is fully embedded in source. +return start point of target in source: i +*/ +public int strStr(String source, String target) { + //Check Null + if(source == null || target == null){ + return -1; + } + //Two Pointer check for target + int i,j; + for (i = 0; i < source.length() - target.length() + 1; i++){ + for (j = 0; j < target.length(); j++){ + if (source.charAt(i+j) != target.charAt(j)){ + break; + } + } + if( j == target.length()){ + return i; + } + } + //'target' not found: + return -1; +} + +--- +**278. [Subarray Sum Closest.java](https://github.com/awangdev/LintCode/blob/master/Java/Subarray%20Sum%20Closest.java)** Level: Medium + +? + + +--- +**279. [Subarray Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Subarray%20Sum.java)** Level: Easy + +分析出,如果sum[0~a]=x, 然后sum[0~b]=x, 说明sum(a ~ b] = 0. + + 这样理解后,用hashMap存每个sum[0~i]的值和index i. 如果有重复,就找到了一组sum为0的数组。 + + +--- +**280. [Subset.java](https://github.com/awangdev/LintCode/blob/master/Java/Subset.java)** Level: Medium + +最基本的递归题目。 +坑:记得一开头sort一下 nums。 因为要升序。那么整体就是O(nlogn) + +注意:用level/index来track到哪一步。最后一level就add into rst + +方法1: subset的概念,取或者不取,backtracking. 当level/index到底,return 一个list. + +方法2: 用for loop backtracking. 记得:每个dfs recursive call是一种独特可能,先加进rst。 + + +recap:时间久了忘记dfs的两种路子. for loop dfs/backtracking vs. regular dfs + + +--- +**281. [Subsets II.java](https://github.com/awangdev/LintCode/blob/master/Java/Subsets%20II.java)** Level: Medium + +递归:找准需要pass along的几个数据结构。 + +和SubsetI类似,先sort input, 然后递归。但是input可能有duplicates. + +Using for loop approach: 每个dfs call是一种可能性,直接add into result. +为了除去duplicated result, 如果在递归里面用rst.contains(),就是O(n), which makes overall O(n^2). + +这里有个基于sorted array的技巧: +因为我们有mark index。 一旦for loop里面的i!=index,并且nums[i] == nums[i-1],说明x=nums[i-1]已经用过,不需要再用一次: +[a,x1,x2],x1==x2 +i == index -> [a,x1] +i == index + 1 -> [a,x2]. 我们要skip这一种。 + +如果需要[a,x1,x2]怎么办? 其实这一种在index变化时,会在不同的两个dfs call 里面涉及到。 + + +Iterative: 写一写,用个Queue. Not recommended, Again, rst.contains() cost too much. + + +--- +**282. [Subtree.java](https://github.com/awangdev/LintCode/blob/master/Java/Subtree.java)** Level: Easy + +找到potential subtree, 比较Children. + +一点注意:即使找到T1 == T2, 但很可能只是数字相同(这里不是binary search tree!!),而children不同。所以同时要继续recursively isSubtree(T1.left, T2) ...etc. + + +--- +**283. [Summary Ranges.java](https://github.com/awangdev/LintCode/blob/master/Java/Summary%20Ranges.java)** +Given a sorted integer array without duplicates, return the summary of its ranges. + +For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. + +Tags: Array +Similar Problems: (M) Missing Ranges + + +*/ +/* +Thoughts: basic implementation, use a arraylist to catch candidates. +Detect condition, and return results. +*/ +public class Solution { + public List summaryRanges(int[] nums) { + List rst = new ArrayList(); + if (nums == null || nums.length == 0) { + return rst; + } + ArrayList list = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + list.add(nums[i]); + if (i + 1 == nums.length || nums[i] + 1 != nums[i + 1]) { + if (list.size() == 1) { + rst.add(list.get(0) + ""); + } else { + rst.add(list.get(0) + "->" + list.get(list.size() - 1)); + } + list = new ArrayList(); + } + } + return rst; + } +} + +//O(n) + +--- +**284. [Surrounded Regions.java](https://github.com/awangdev/LintCode/blob/master/Java/Surrounded%20Regions.java)** +Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. + +A region is captured by flipping all 'O's into 'X's in that surrounded region. + +For example, +X X X X +X O O X +X X O X +X O X X +After running your function, the board should be: + +X X X X +X X X X +X X X X +X O X X +Hide Tags Breadth-first Search + +Thinking Process: +Since dfs does not work, try bfs. +Very similar to DFS, however, when checking the 4 bounaries: +1. chcek the curruent point. +2. Add surrounding points into a queue. +3. Deal with the queue immediately via a while loop + +*/ +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + private Queue queue = new LinkedList(); + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + row = board.length; + col = board[0].length; + target = 'O'; + mark = 'M'; + //Check the board + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || i == row - 1 || j == 0 || j == col - 1) { + check(i,j); + } + } + } + //Replacement + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } + if (board[i][j] == mark) { + board[i][j] = target; + } + } + } + } + //BFS + public void check(int i, int j) { + fill(board, i, j); + while(!queue.isEmpty()) { + int val = queue.poll(); + int x = val / col; + int y = val % col; + fill(board, x - 1, y); + fill(board, x + 1, y); + fill(board, x, y - 1); + fill(board, x, y + 1); + } + } + public void fill(char[][] board, int i, int j) { + if (i < 0 || i >= row || j < 0 || j >= col || board[i][j] != target) { + return; + } + board[i][j] = mark; + queue.offer(i * col + j); + } +} + + + + +/* +Thinking process: +Using DFS. +1. Whenever the edge has an 'O', all touching point with 'O' will be non-surrounded by 'X'. SO check the 4 bounds first. Mark all non-surrounded point as M. +2. Replace all remaining 'O' with 'X' +3. Replace 'M' with 'O' +However, in the LeetCode test, DFS gives stack overflow. So we'd use BFS instead. +*/ + +/* + +//The following is using DFS, but gives Stackoverflow. +public class Solution { + private char[][] board; + private int row; + private int col; + private char target; + private char mark; + public void solve(char[][] board) { + if (board == null || board.length == 0) { + return; + } + this.board = board; + target = 'O'; + mark = 'M'; + row = board.length; + col = board[0].length; + + //check bound + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (i == 0 || j == 0 || i == row - 1 || j == col - 1) { + check(i, j); + } + } + } + //1. replace remaining target with 'x' + //2. replace all mark with 'O' + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (board[i][j] == target) { + board[i][j] = 'X'; + } else if (board[i][j] == mark) { + board[i][j] = 'O'; + } + } + } + } + + public void check(int i, int j) { + if (i < 0 || j < 0 || i > row - 1 || j > col - 1) { + return; + } + if (board[i][j] == target) { + board[i][j] = mark; + check(i - 1, j); + check(i + 1, j); + check(i, j - 1); + check(i, j + 1); + } + } + +} + +*/ + +--- +**285. [Swap Nodes in Pairs.java](https://github.com/awangdev/LintCode/blob/master/Java/Swap%20Nodes%20in%20Pairs.java)** +画三个block, 1,2,3. 连线。 + +--- +**286. [Symmetric Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Symmetric%20Binary%20Tree.java)** Level: Easy + +注意Symmetric Binary Tree的例子和定义: 是镜面一样的对称. 并不是说左右两个sub-tree相等。 + +方法1: Recursively check symmetrically相对应的Node. 每个node的children都和镜面另外一边相对的node的children刚好成镜面反射位置。 + +方法2: 用stack. 左手边sub-tree先加left,再加right child; 右手边sub-tree先加right child, 再加left child。 +process时,若symmetric,所有stack里面出来的node会一一对应。 + + +--- +**287. [The Smallest Difference.java](https://github.com/awangdev/LintCode/blob/master/Java/The%20Smallest%20Difference.java)** +Given two array of integers(the first array is array A, the second array is array B), now we are going to find a element in array A which is A[i], and another element in array B which is B[j], so that the difference between A[i] and B[j] (|A[i] - B[j]|) is as small as possible, return their smallest difference. + + +Example +For example, given array A = [3,6,7,4], B = [2,8,9,3], return 0 + +Challenge +O(n log n) time + +Tags Expand +Two Pointers LintCode Copyright Sort Array +*/ + +/* + Thoughts: + Sort A, B. O(nLogn) + Use smaller array to binarh in longer array. n * logn + +*/ + + +public class Solution { + /** + * @param A, B: Two integer arrays. + * @return: Their smallest difference. + */ + public int smallestDifference(int[] A, int[] B) { + if (A == null || A.length == 0 || B == null || B.length == 0) { + return 0; + } + if (A.length > B.length) { + int[] temp = A; + A = B; + B = temp; + } + Arrays.sort(A); + Arrays.sort(B); + int diff = Integer.MAX_VALUE; + + for (int i = 0; i < A.length; i++) {//10 + int start = 0; + int end = B.length - 1; + int mid; + //Small enhancement + if (B[start] >= A[A.length - 1]) { + return B[start] - A[A.length - 1]; + } + if (A[start] >= B[B.length - 1]) { + return A[start] - B[B.length - 1]; + } + while (start + 1 < end) { + mid = start + (end - start)/2; + if (B[mid] == A[i]) { + return 0; + } else if (mid - 1 >= 0 && B[mid - 1] < A[i] && A[i] < B[mid]) { + diff = Math.min(diff, Math.min(A[i] - B[mid - 1], B[mid] - A[i])); + break; + } else if (mid + 1 < B.length - 1 && B[mid] < A[i] && A[i] < B[mid + 1]) { + diff = Math.min(diff, Math.min(A[i] - B[mid], B[mid + 1] - A[i])); + break; + } else if (B[mid] > A[i]) { + end = mid; + } else { + start = mid; + } + + }//end while + if (start + 1 >= end) { + int min = Math.min(Math.abs(A[i] - B[start]), Math.abs(A[i] - B[end])); + diff = Math.min(diff, min); + } + }//end for + return diff; + } +} + + + + + + + + + +--- +**288. [Top K Frequent Words.java](https://github.com/awangdev/LintCode/blob/master/Java/Top%20K%20Frequent%20Words.java)** Level: Medium + +方法1:Brutle force用HashMap存frequency, 用ArrayList存lists of words。最后返回从尾部向前数的k个。 + 注意排序时Collection.sort()的cost是O(nLogk) + +方法1-1: 还是用HashMap,但create一个Node class, 然后用PriorityQueue. +PriorityQueue里面用到了 String.compareTo(another String).巧妙。 + +方法2: Trie && MinHeap屌炸天 + http://www.geeksforgeeks.org/find-the-k-most-frequent-words-from-a-file/ + + +--- +**289. [Topological Sorting.java](https://github.com/awangdev/LintCode/blob/master/Java/Topological%20Sorting.java)** Level: Medium + +比较特别的BFS. + +几个graph的condition: +1. 可能有多个root +2. directed node, 可以direct backwards. + +Steps: +Track all neighbors/childrens. 把所有的children都存在map里面 +先把所有的root加一遍,可能多个root。并且全部加到queue里面。 + +然后以process queue, do BFS: +Only when map.get(label) == 0, add into queue && rst. +这用map track apperance, 确保在后面出现的node, 一定最后process. + + + +--- +**290. [Total Occurrence of Target.java](https://github.com/awangdev/LintCode/blob/master/Java/Total%20Occurrence%20of%20Target.java)** +找total number of occurance. 首先找first occurance, 再找last occurance. + +--- +**291. [Trailing Zeros.java](https://github.com/awangdev/LintCode/blob/master/Java/Trailing%20Zeros.java)** +Write an algorithm which computes the number of trailing zeros in n factorial. + +Example +11! = 39916800, so the out should be 2 + +Challenge +O(log N) time + +Tags Expand +Mathematics + +Thoughts: +Attempt1: +Can this problem be converted to : how many 10's to I have? +Loop through n, and check how many 2s, 5s do we have. +For each i, do while loop and count the number of 2s, and 5s in that particular i. + +Note: +5 and 2 makes 10. So don't worry about 10. +Some values will be checked redundantly, so record the ones checked, return the hash value directly. + +Attempt2: +Don't even need to worry about 2's because 2 is definitely more than 5's. Only need to care about 5's. + +How many 5's? n/5. loop (1 ~ n) +However, some number within (1 ~ n) may give more 5's, which for example is: 25 = 5 * 5, double 5's. And 125 = triple 5's. + +In fact count = n / 5 + n / 25 + n / 125 + .... +*/ +class Solution { + /* + * param n: As desciption + * return: An integer, denote the number of trailing zeros in n! + */ + public long trailingZeros(long n) { + if ( n < 5) { + return 0; + } + long count = 0; + for (long i = 5; n / i != 0; i *= 5) { + count += n / i; + } + return count; + } + +} + + + +/* +//Attempt 1: +//This solution exceed time limit, and it's over-complex. 滚粗。 +class Solution { + + private HashMap mapTwo = new HashMap(); + private HashMap mapFive = new HashMap(); + public long trailingZeros(long n) { + if (n < 5) { + return 0; + } + long countFive = 0; + long countTwo = 0; + for (int i = 1; i <= n; i++) { + if (i % 2 == 0) { + countTwo += countExistance(i, 2, mapTwo); + } + if (i % 5 == 0) { + countFive += countExistance(i, 5,mapFive); + } + } + return (countFive < countTwo) ? countFive : countTwo; + } + public long countExistance(long n, long m, HashMap map) { + long temp = n; + long count = 0; + double num = (double)n; + while (num / m == n / m) { + count++; + n = n / m; + num = (double)n; + if (map.containsKey(n)) { + count += map.get(n); + break; + } + } + if (!map.containsKey(temp)) { + map.put(temp, count); + } + return count; + } +}; + +*/ + +--- +**292. [Trapping Rain Water II.java](https://github.com/awangdev/LintCode/blob/master/Java/Trapping%20Rain%20Water%20II.java)** Level: Hard + +用PriorityQueue把选中的height排序。为走位,create class Cell {x,y, height}. + +注意几个理论: +1. 从matrix四周开始考虑,发现matrix能Hold住的水,取决于height低的block。 +2. 必须从外围开始考虑,因为水是被包裹在里面,外面至少需要现有一层。 + +以上两点就促使我们用min-heap: 也就是natural order的PriorityQueue. + +process的时候,画个图也可以搞清楚,就是四个方向都走走,用curr cell的高度减去周围cell的高度。 若大于零,那么就有积水。 + +每个visited的cell都要mark. 去到4个方向的cell,加进queue里面继续process. + +这里,有一点,和trapping water I 想法一样。刚刚从外围,只是能加到跟外围cell高度一致的水平面。往里面,很可能cell高度变化。 +这里要附上curr cell 和 move-to cell的最大高度。 + + +--- +**293. [Trapping Rain Water.java](https://github.com/awangdev/LintCode/blob/master/Java/Trapping%20Rain%20Water.java)** Level: Medium + +2 Pointers, 双面夹击: +1. 找中间最高bar的index +2. 两面往中心扫:每次加上(topBarIndex - currIndex)* (elevation from previous index).也就是每次加一个横条。 +3. 每次还要减去block自身的height。 + + +--- +**294. [Triangle Count.java](https://github.com/awangdev/LintCode/blob/master/Java/Triangle%20Count.java)** +Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find? + +Example +Given array S = [3,4,6,7], return 3. They are: + +[3,4,6] +[3,6,7] +[4,6,7] +Given array S = [4,4,4,4], return 4. They are: + +[4(1),4(2),4(3)] +[4(1),4(2),4(4)] +[4(1),4(3),4(4)] +[4(2),4(3),4(4)] +Tags Expand +Two Pointers LintCode Copyright +*/ + +/* +Thoughts: +Pick 3 integers that fits the condition: +A + B > C +B + C > A +A + C > B +If we sort the input, then we know A <= B <= C, so we can remove 2 conditoins above and only have: +A + B > C +That is, Pick one C, and pick two integers A,B in front. Similar to TWO SUM II. +Have a fixed C as target, and find A + B > target in the remaining array on left of C. +How about just use 2 pointers left, right, and compare with a C (s[i] in for loop) +Time: O(n^2) + +Note: don't forget to sort +*/ + +public class Solution { + /** + * @param S: A list of integers + * @return: An integer + */ + public int triangleCount(int S[]) { + if (S == null || S.length == 0) { + return 0; + } + Arrays.sort(S); + int count = 0; + for (int i = 0; i < S.length; i++) { + int left = 0; + int right = i - 1; //at least 1 step left from C + while (left < right){ + if (S[left] + S[right] > S[i]) { + count += (right - left); + right--; + } else {//(S[left] + S[right] <= S[i]) + left++; + } + } + } + return count; + } +} + + +--- +**295. [Tweaked Identical Binary Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Tweaked%20Identical%20Binary%20Tree.java)** Level: Easy + +Recursive 比对左左,左右,右左,右右 + + +--- +**296. [Two Lists Sum.java](https://github.com/awangdev/LintCode/blob/master/Java/Two%20Lists%20Sum.java)** +You have two numbers represented by a linked list, where each node contains a single digit.The digits are stored in reverse order, such that the 1’s digit is at the head of the list.Write a function that adds the two numbers and returns the sum as a linked list. + +Example +Given two lists, 3->1->5->null and 5->9->2->null, return 8->0->8->null + +Tags Expand +Linked List Backtracking +//TODO: check 9chapter solution +Thinking process: +Simply add 2 lists’ values together. +Handle the carrier +Use dummy node at beginning. +*/ + +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + /** + * @param l1: the first list + * @param l2: the second list + * @return: the sum list of l1 and l2 + */ + public ListNode addLists(ListNode l1, ListNode l2) { + ListNode rst = new ListNode(0); + ListNode dummy = rst; + int carrier = 0; + //while + while (l1 != null || l2 != null) { + if (l1 != null) { + carrier += l1.val; + l1 = l1.next; + } + if (l2 != null) { + carrier += l2.val; + l2 = l2.next; + } + rst.next = new ListNode(carrier % 10); + carrier = carrier / 10; + rst = rst.next; + } + //check the carrier + if (carrier == 1) { + rst.next = new ListNode(1); + } + return dummy.next; + } +} + + +--- +**297. [Two Strings Are Anagrams.java](https://github.com/awangdev/LintCode/blob/master/Java/Two%20Strings%20Are%20Anagrams.java)** Level: Easy + +方法1:char ascii 用count[256] +坑:不要想象这个是个26letter lowercase. may not be true. + +方法2: 若是其他字符encoding, 而不只是utf16-encoding (java char)? +那么就继续用string去做 + + +--- +**298. [Ugly Number II.java](https://github.com/awangdev/LintCode/blob/master/Java/Ugly%20Number%20II.java)** +每次把dp[i-1]拿出来,不管三七二十一,分别乘以2,3,5. 出来的结果放进priority queue做比较。 +最后时间是n*log(n*3) + +注意: +Long +HashSet确保没有重复。 + +--- +**299. [Ugly Number.java](https://github.com/awangdev/LintCode/blob/master/Java/Ugly%20Number.java)** Level: Medium + +方法1: PriorityQueue排序。用ArrayList check 新的ugly Number是否出现过。 + +方法1-1:(解释不通,不可取)用PriorityQueue排序。神奇的3,5,7走位:按照题目答案的出发,定了3,5,7以什么规律出现。但是题目并没有特殊表明。 + +方法2: DP . Not Done yet. + + + +--- +**300. [Unique Binary Search Tree II.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Binary%20Search%20Tree%20II.java)** +Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. + +Example +Given n = 3, your program should return all 5 unique BST's shown below. + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 +Tags Expand +Dynamic Programming Depth First Search + +Thinking process: +- For a BST, root can be any node from node(1) to node(n). +- For each root, left nodes has mutiple forms of BST, and right node has mutiple forms of BST. +- For each root node, divide and conquer left / right +*/ + +/** + * Definition of TreeNode: + * public class TreeNode { + * public int val; + * public TreeNode left, right; + * public TreeNode(int val) { + * this.val = val; + * this.left = this.right = null; + * } + * } + */ +public class Solution { + /** + * @paramn n: An integer + * @return: A list of root + */ + public List generateTrees(int n) { + return generate(1, n); + } + public ArrayList generate(int start, int end) { + ArrayList rst = new ArrayList(); + if (start > end) { + rst.add(null); + return rst; + } + for (int i = start; i <= end; i++){ + ArrayList left = generate(start, i - 1); + ArrayList right = generate(i + 1, end); + for (TreeNode l : left) { + for (TreeNode r : right) { + TreeNode root = new TreeNode(i); + root.left = l; + root.right = r; + rst.add(root); + } + } + } + return rst; + } +} + + +--- +**301. [Unique Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Binary%20Search%20Tree.java)** +Given n, how many structurally unique BST's (binary search trees) that store values 1...n? + + + +Example +Given n = 3, there are a total of 5 unique BST's. + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 +Tags Expand +Catalan Number Dynamic Programming + +Thinking proces: +Knowing what is Catalan number. +C(n+1) = SUM(C(i)*C(n-i)) +OR: C(n) = SUM(C(i)*C(n-i-1)). +*/ + +public class Solution { + /** + * @paramn n: An integer + * @return: An integer + */ + public int numTrees(int n) { + if (n <= 1) { + return 1; + } + int[] count = new int[n + 1]; + count[0] = 1; + count[1] = 1; + for (int i = 2; i < n + 1; i++) { + for (int j = 0; j < i; j++) { + count[i] += count[j] * count[i - j - 1]; + } + } + return count[n]; + } +} + +--- +**302. [Unique Characters.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Characters.java)** +用hashSet, space O(n), time O(n) + +--- +**303. [Unique Path.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Path.java)** Level: Medium + + +--- +**304. [Unique Paths II.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Paths%20II.java)** +Follow up for "Unique Paths": + +Now consider if some obstacles are added to the grids. How many unique paths would there be? + +An obstacle and empty space is marked as 1 and 0 respectively in the grid. + +Note +m and n will be at most 100. + +Example +For example, +There is one obstacle in the middle of a 3x3 grid as illustrated below. + +[ + [0,0,0], + [0,1,0], + [0,0,0] +] +The total number of unique paths is 2. + +Tags Expand +Array Dynamic Programming + +Thinking process: +1. Still use an extra matrix to count possible paths. +2. When initializing, skip block if it's obstacle (break the for loop, basically skip this row/col) +3. When evaluating paths, skip block if it's obstacle (save current spot's path as 0, means no path through this point). +4. Note: At evaluating double-for loop, we cannot use break, because we still need to evaluate using upper/left block. Hence we set the obstacle = 0. +*/ + +public class Solution { + /** + * @param obstacleGrid: A list of lists of integers + * @return: An integer + */ + public int uniquePathsWithObstacles(int[][] obstacleGrid) { + if (obstacleGrid == null || obstacleGrid.length == 0 || obstacleGrid[0].length == 0) { + return 0; + } + int row = obstacleGrid.length; + int col = obstacleGrid[0].length; + int[][] matrix = new int[row][col]; + for (int i = 0; i < row; i++) { + if (obstacleGrid[i][0] == 1) { + break; + } else { + matrix[i][0] = 1; + } + } + for (int j = 0; j < col; j++) { + if (obstacleGrid[0][j] == 1) { + break; + } else { + matrix[0][j] = 1; + } + } + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + if (obstacleGrid[i][j] == 1) { + matrix[i][j] = 0; + } else { + matrix[i][j] = matrix[i - 1][j] + matrix[i][j - 1]; + } + } + } + return matrix[row - 1][col - 1]; + } +} + + +--- +**305. [Unique Word Abbreviation.java](https://github.com/awangdev/LintCode/blob/master/Java/Unique%20Word%20Abbreviation.java)** +An abbreviation of a word follows the form . Below are some examples of word abbreviations: + +a) it --> it (no abbreviation) + + 1 +b) d|o|g --> d1g + + 1 1 1 + 1---5----0----5--8 +c) i|nternationalizatio|n --> i18n + + 1 + 1---5----0 +d) l|ocalizatio|n --> l10n +Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation. + +Example: +Given dictionary = [ "deer", "door", "cake", "card" ] + +isUnique("dear") -> false +isUnique("cart") -> true +isUnique("cane") -> false +isUnique("make") -> true + +Tags: Hash Table, Design +Similar Problems: (E) Two Sum III - Data structure design + + + +*/ +/* +Thought: +Originally, used a hashset to store all existing pattern. If checked word exist in dict hashset, then return false. +However, there is a case that: the word existed in the dict only for once, which is by accident the same as the checked work, then return true. +Therefore, we need to keep track of what word has been catagrize into pattern. SO, use a HashMap instead. + +Note: Dealing with char, integer, string. Be careful if char are turnning int integers. +*/ +public class ValidWordAbbr { + HashMap> map; + public ValidWordAbbr(String[] dict) { + if (dict == null || dict.length == 0) { + return; + } + map = new HashMap>(); + for (String s : dict) { + String str = ""; + if (s.length() <= 2) { + str = s; + } else { + str += s.charAt(0) + (s.length() - 2 + "") + s.charAt(s.length() - 1); + } + if (!map.containsKey(str)) { + ArrayList list = new ArrayList(); + list.add(s); + map.put(str, list); + } else { + if (!map.get(str).contains(s)) { + map.get(str).add(s); + } + + } + } + } + + public boolean isUnique(String word) { + if (map == null || map.size() == 0) { + return true; + } + String str = ""; + if (word.length() <= 2) { + str = word; + } else { + str += word.charAt(0) + (word.length() - 2 + "") + word.charAt(word.length() - 1); + } + if (map.containsKey(str) && map.get(str).size() == 1 && map.get(str).get(0).equals(word)) { + return true; + } + return !map.containsKey(str); + } +} + + + + + +// Your ValidWordAbbr object will be instantiated and called as such: +// ValidWordAbbr vwa = new ValidWordAbbr(dictionary); +// vwa.isUnique("Word"); +// vwa.isUnique("anotherWord"); + +--- +**306. [Update Bits.java](https://github.com/awangdev/LintCode/blob/master/Java/Update%20Bits.java)** +Given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j) + + + +Example +Given N = (10000000000)2, M = (10101)2, i = 2, j = 6 + +return N = (10001010100)2 + +Challenge +Minimum number of operations? + +Tags Expand +Cracking The Coding Interview Bit Manipulation Binary Representation + +Thinking process: +Create a mask: xxxx000000xxxx. +Trick part: when it encounters negative number or dealing with index at edge index = 31, it starts having issue. Interesting fix: use long for masks. +*/ + +class Solution { + /** + *@param n, m: Two integer + *@param i, j: Two bit positions + *return: An integer + */ + public int updateBits(int n, int m, int i, int j) { + //Create mask: xxx00000xxx + long rightMask = ~0 >> i; + rightMask = ~(rightMask << i);// 00000xxx + long leftMask = ~0 >> (j + 1); + leftMask = leftMask << (j + 1);//xxxxx00000000 + long mask = leftMask | rightMask;//xxx00000xxx + n = (int) (n & mask); + n = (int) (n | (m << i)); + return n; + } +} + + + +--- +**307. [Valid Anagram.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Anagram.java)** +Given two strings s and t, write a function to determine if t is an anagram of s. + +For example, +s = "anagram", t = "nagaram", return true. +s = "rat", t = "car", return false. + +Note: +You may assume the string contains only lowercase alphabets. + +Follow up: +What if the inputs contain unicode characters? How would you adapt your solution to such case? + +Tags: Hash Table, Sort +Similar Problems: (M) Group Anagrams, (E) Palindrome Permutation + + +*/ +/* +Thoughts: +Anagram: reorder of letters. +Use HashMap to store the frequency of chars of 1st string, and check aginst 2nd string. +s character: +1; +t character: -1; +check count of each index in the map; they should all be 0 +*/ + + +public class Solution { + public boolean isAnagram(String s, String t) { + if (s == null || t == null) { + return s == null && t == null; + } else if (s.length() != t.length()) { + return false; + } + + HashMap map = new HashMap(); + for (int i = 0; i < s.length(); i++) { + if (!map.containsKey(s.charAt(i))) { + map.put(s.charAt(i), 1); + } else { + map.put(s.charAt(i), map.get(s.charAt(i)) + 1); + } + if (!map.containsKey(t.charAt(i))) { + map.put(t.charAt(i), -1); + } else { + map.put(t.charAt(i), map.get(t.charAt(i)) - 1); + } + }//END for + + for (int i = 0; i < s.length(); i++) { + if (map.get(s.charAt(i)) != 0) { + return false; + } + } + return true; + } +} + +--- +**308. [Valid Palindrome.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Palindrome.java)** Level: Easy + [Tutorial Link](https://www.youtube.com/watch?v=2hNK0Yz53LQ&list=PLZn-UvluQZuNedn1hDzTmNLE8MQWXjKVb) + +过滤alphanumeric,其他字母掠过 + + +--- +**309. [Valid Parentheses.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Parentheses.java)** Level: Easy + +剥皮过程。解铃还须系铃人 +左边的外皮'{['在stack底部 +右边的外皮应该和stack顶上的左外皮一一对应 + + + + +--- +**310. [Valid Sudoku.java](https://github.com/awangdev/LintCode/blob/master/Java/Valid%20Sudoku.java)** Level: Easy + +用HashSet存visited value. + +方法1: 在nest for loop里面validate row,col,and block. +validate block要利用i 和 j 增长的规律。 +说白了,i && j是按照0~n增长的index, 具体怎么用是可以flexible的。这个方法在同一个nest for loop解决所有运算。 + +方法2: 单独做block validation: validate block的时候虽然看到了4层for.其实也就是n^2. + + +--- +**311. [Validate Binary Search Tree.java](https://github.com/awangdev/LintCode/blob/master/Java/Validate%20Binary%20Search%20Tree.java)** Level: Medium + +查看每个parent-child关系。同时把root level上面传下来max,min界限定住。 + + +--- +**312. [Wiggle Sort.java](https://github.com/awangdev/LintCode/blob/master/Java/Wiggle%20Sort.java)** +这样的fall-through每次在乎两个element,可以一口气搞定,无关乎再之前的elements。 +特别的一点:flag来巧妙的掌控山峰和低谷的变化。又是神奇的一幕啊! + +这样子的奇观,见过就要知道了,没见过的时候有点摸不着头脑。 + +--- +**313. [Wood Cut.java](https://github.com/awangdev/LintCode/blob/master/Java/Wood%20Cut.java)** +Given n pieces of wood with length L[i] (integer array). Cut them into small pieces to guarantee you could have equal or more than k pieces with the same length. What is the longest length you can get from the n pieces of wood? Given L & k, return the maximum length of the small pieces. + +Note +You couldn't cut wood into float length. + +Example +For L=[232, 124, 456], k=7, return 114. + +Challenge +O(n log Len), where Len is the longest length of the wood. + +Tags Expand +Binary Search + +Thinking process: +Take the largest item. +Priorities: +1. Have to get calculatedK >= givenK +2. Meanwhile, want to maximize the smal piece. + +One thing not clear: do we have to use the given small piece? If we have to, we need to concern about the shortest wood piece. See commentted-out part +In this problem, however, we can abandon the small pieces, as long as the max_small_pieces can allow calculatedK >= givenK. + +Use binary search on the largest item: +1. if calculatedK < givenK: end = mid; +2. If calculated >= givenK, move start = mid as much as possible, which gives maximized small piece. + +*/ + + +public class Solution { + /** + *@param L: Given n pieces of wood with length L[i] + *@param k: An integer + *return: The maximum length of the small pieces. + */ + public int woodCut(int[] L, int k) { + if (L == null || L.length == 0 || k < 0) { + return 0; + } + if (L.length == 1) { + return L[0] / (L[0] / k); + } + Arrays.sort(L); + int start = 0; + int end = L[L.length - 1]; + int mid = 0; + int max = 0; + // int min = L[0]; + while (start + 1 < end) { + mid = start + (end - start) / 2; + //if (mid > min) { + // end = mid; + // } else { + int count = 0; + for (int i : L) { + count += i / mid; + } + if (count < k) { + end = mid; + } else { + start = mid; + max = mid; + } + //} + }//end while + return max; + } +} + + +--- +**314. [Word Break II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Break%20II.java)** Level: Hard + +两个DP一起用.解决了timeout的问题 +1. isWord[i][j], subString(i,j)是否存在dict中? + +2. 用isWord加快 isValid[i]: [i ~ end]是否可以从dict中找到合理的解? + 从末尾开始查看i:因为我们需要测试isWord[i][j]时候,j>i, 而我们观察的是[i,j]这区间; + j>i的部分同样需要考虑,我们还需要知道isValid[0~j+1]。 所以isValid[x]这次是表示[x, end]是否valid的DP。 + i 从 末尾到0, 可能是因为考虑到isWord[i][j]都是在[0~n]之内,所以倒过来数,坐标比较容易搞清楚。 + (回头看Word Break I, 也有坐标反转的做法) + +3. dfs 利用 isValid 和isWord做普通的DFS。 + +Note: +在Word Break里面用了set.contains(...), 在isValid里面,i 从0开始。 但是,contains()本身是O(n). +在这道题里面应该是因为word dictionary太大,加上nest for, 变成O(n^3)所以timeout. + +istead,用一个isWord[i][j],就O(1)判断了i~j是不是存在dictionary里面。 + + +--- +**315. [Word Break.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Break.java)** Level: Medium + +DP + +方法1:(attempt3 code) +state,rst[i]: 从[0~i] inclusive的string是否可以在dict中break开来找到? +function: rst[i] = true if (rst[i - j] && set.contains(s.substring(i - j, i))); j in[0~i] +1. rst[i - j] 记录的是[0, i-j]这一段是否可以break后在dict找到。 +2. 若true,再加上剩下所有[i-j, i]都能在dict找到,那么rst[i] = rst[0, i - j] && rst[i-j, i] == true + +优化:找dict里面最长string, 限制j的增大。 + +(attempt4 code) +与Word BreakII用同样的DP。 +valid[i]: 记录从i到valid array末尾是否valid. + + +--- +**316. [Word Ladder II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Ladder%20II.java)** Level: Hard + + +--- +**317. [Word Ladder.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Ladder.java)** Level: Medium + +BFS Brutle: 在start string基础上,string的每个字母都遍历所有26个字母,换换。 + +方法2: +用Trie。 理应更快. However implementation可能有点重复计算的地方,LeetCode timeout. 需要再做做。 + + +--- +**318. [Word Pattern.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Pattern.java)** Level: Easy + +每个char代表一个pattern。用HashMap. +但不够,如果a也match dog, b也match dog, 纠错了。比如pattern = "abba", str = "dog dog dog dog"。 +因此第二个HashMap 反过来。 +确保pattern和str一一对应。 + + +--- +**319. [Word Search II.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Search%20II.java)** Level: Hard + +Big improvement: use boolean visited on TrieNode! +不要用rst.contains(...), 因为这个是O(n) 在leetcode还是会timeout(lintcode竟然可以pass)! +在Trie search() method 里面,凡是visit过的,mark一下。 + +Regular: +for loop on words: inside, do board DFS based on each word. +Time cpmplexity: word[].length * boardWidth * boardHeight * (4^wordMaxLength) + +Build Trie with target words: insert, search, startWith. +依然要对board matrix做DFS。 + +no for loop on words. 直接对board DFS: +每一层,都会有个up-to-this-point的string. 在Trie里面check它是不是存在。以此判断。 +若不存在,就不必继续DFS下去了。 + +Trie solution time complexity, much better: +build Trie: n * wordMaxLength +search: boardWidth * boardHeight * (4^wordMaxLength + wordMaxLength[Trie Search]) + + + +--- +**320. [Word Search.java](https://github.com/awangdev/LintCode/blob/master/Java/Word%20Search.java)** Level: Medium + +Backtracking: +比较 Brutle。找到开头的字母,然后投入一个recursive找字母的工程:每到一个字母,朝四个方向走。他们之中,有一个true就可以。 + +Note:每次到一个字母,mark一下'#'. 4个path recurse回来后,mark it back. + +Backtracking方法2: +用一个boolean visited[][] + + + + +--- +**321. [Zigzag Iterator.java](https://github.com/awangdev/LintCode/blob/master/Java/Zigzag%20Iterator.java)** +每次next(), 相应的list的头拿下来就好。 +然后就跑圈呗,每次刷一个list头。不难。只要把几个variable维护清楚就行。 + +--- diff --git a/Solution$ListNode.class b/Solution$ListNode.class deleted file mode 100644 index 9246a9c..0000000 Binary files a/Solution$ListNode.class and /dev/null differ diff --git a/Solution.class b/Solution.class index f85e850..e3ea508 100644 Binary files a/Solution.class and b/Solution.class differ diff --git a/Solution.java b/Solution.java index 2f333ed..ea3e200 100644 --- a/Solution.java +++ b/Solution.java @@ -1,76 +1,103 @@ +import java.io.*; import java.util.*; -public class Solution { - static int index; - static HashMap> map; - static Queue queue; + + + +/* + * To execute Java, please define "static void main" on a class + * named Solution. + * + * If you need more classes, simply define them inline. + */ + +// +class Solution { + + + public static ArrayList validateClock() { + //p:1, n:5, d: 10 + int[] nums = {1,1,1,1,5,5,5,5,10,10,10,10}; + ArrayList rst = new ArrayList(); + ArrayList list = new ArrayList(); + + helper(rst, " ", 4,4,4); + + return rst; - public static void ZigzagIterator(List v1, List v2) { - map = new HashMap>(); - queue = new LinkedList(); - index = 0; - if (v1 != null) { - map.put(0, v1); - } - if (v2 != null) { - map.put(1, v2); - } - - //init with head item - for (Map.Entry> entry : map.entrySet()) { - queue.offer(entry.getValue().get(0)); - entry.getValue().remove(0); - index++; - if (index == map.size()) { - index = 0; - } - } + } + + public static void helper(ArrayList rst, ArrayList list, int[] nums, int p, int n, int d) { + if (p < 0 || n < 0 || d < 0) { + return; + } + if (list.size() == nums.length) { + if (validate(list)) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < list.size(); i++) { + if (list.get(i) == 1) sb.append("P"); + if (list.get(i) == 5) sb.append("N"); + if (list.get(i) == 10) sb.append("D"); + } + rst.add(sb.toString()); + } + return; + } + + for (int i = 0; i < nums.length; i++) { + if (nums[i] == 1 && p > 0) { + list.add(nums[i]); + helper(rst, list, nums, p - 1, n, d); + } + else if (nums[i] == 5 && n > 0) { + list.add(nums[i]); + helper(rst, list, nums, p, n - 1, d); + } + + else if (nums[i] == 10 && n > 0) { + list.add(nums[i]); + helper(rst, list, nums, p, n, d - 1); + } + list.remove(list.size() - 1); } - - public static int next() { - int next = queue.poll(); - while (true) { - if (map.get(index).size() != 0) { - queue.offer(map.get(index).get(0)); - map.get(index).remove(0); - index++; - if (index == map.size()) { - index = 0; - } - break; - } - index++; - if (index == map.size()) { - index = 0; - break; - } - } - return next; + + } + + public static boolean validate(String str) {//{p}, 0, c = + if (str == null || str.length() < 12) { + return false; } - - public static boolean hasNext() { - return !queue.isEmpty(); + String[] arr = str.split(" "); + String[] test = {" "," "," "," "," "," "," "," "," "," "," "," "}; + + for (int i = 0; i < arr.length; i++) { + int num = Integer.parseInt(arr[i]); + + if (num + i >= 12) { + int index = (num + i) % 12; + if (!test[index].equals(" ")) { + return false; + } else { + test[i] = arr[i]; + } + } } - - - public static void main(String[] args){ - System.out.println("START"); - List v1 = new ArrayList(); - List v2 = new ArrayList(); - v1.add(1);v1.add(3); - v2.add(2); v2.add(4); - ZigzagIterator(v1, v2); - - System.out.println(hasNext()); - - System.out.println("END " ); + return true; + } + + + + public static void main(String[] args) { + ArrayList rst = validateClock(); + + for (String string : rst) { + System.out.println(string); } + } } - - - +///Generate all possible solutions, then validate them all. diff --git a/SystemDesign.md b/SystemDesign.md new file mode 100755 index 0000000..a913296 --- /dev/null +++ b/SystemDesign.md @@ -0,0 +1,270 @@ +This document is to document the learning process for **System Design**. +A few concepts to research: +How to split data between servers? How do multiple server communicate? MapReduce? +How does server process heavy calculation in background? Threading? NodeJS threading? + +## Good Concepts: +- For any system, consider: how much data does the system handle? how much data does the system need to store? +- Popular hashing algorithm: like 35. What about md5? +- Scalibility + +## Steps: +1. **Scope** the problem: Don't make assumptions; Ask questions; Understand the constraints and use cases. +2. Sketch up an **abstract design** that illustrates the basic components of the system and the relationships between them. +3. Think about the **bottlenecks** these components face when the system scales. +4. Address these bottlenecks by using the fundamentals principles of **scalable** system design. + +- Mine Usual steps: might be too much details on scoping but less efforts onto bottlenecks and scalibility issues. +1. Identify the key requirements && constraints +2. Identify the users && Server +3. Identify inputs/ouputs from different users +*** Calculate the bandwidth and storage: the amount of data the server handles, and the amount of data server stores. +4. Based on (1~3), list out the potential features that needs to be implemented +5. Pick technologies that will be able to implement the features above: + * backend server + * user client + * method of storage + * method of data trasmissio +6. How does the system scale? What are the limits and trade-off in current design? What improvmenet can be done to design it differently? + + + +## Scalibility lecture +- key concepts: + Vertical scaling: add more cpu,ram,hard-drive + Horizontal scaling:add more cheaper computer, distribute traffice && storage into these machiens. + Caching: save some pre-processed data, like sticky session, pre-quried sqls + Load balancing: determine which web server to hit; determine which db to hit if having multiple db + Database replication: for faster read; for reduancy safety + Database partitioning: for faster performance for some contents, or distributed storage + Using NoSQL instead of scaling a relational database + Being asynchronous + +- Load Balancer? + load balancer is even good to protect server: now backend server can be on LAN with load balancer, so they are protected; and we just expose load balancer to clients. + How does load balancer work? + There are lots of trade-offs: look at 30:00 of the video. That's all the tradeoffs (http://www.hiredintech.com/system-design/scalability-fundamentals/) + - round robin: the load balancer works as a fancy DNS machine, take turns to assign task/request to machine 1,2,3,4...etc. (if we do `nsloopup google.com` on google.com, we can see google does that) + - store states/sessions into a dedicated server. but it indroduces server-failure issue. -use RAID, raplication + RAID0: strip data at two hardrives, little on each + RAID1: mirror data. store at both places + RAID10: combination of RAID0 && RAID1. + RAID5: 3 drives only 1 of them is used for reduendency. + RAID6: multiple drives. any drive can die, then replace, and no data lost. + - split by the type of files request: html server, image server; load balancer + - split based on actual load (less possible), send package to less busy server + Options: + Software: + ELB: elastic load balancer + HAProxy + LVS + hardware: + Barracuda + Cisco + Citrix: over-priced, $20k + F5 + Problem: sticky session (if you revisit the site multiple times seprately, you will still hit the same server) + - can store serverID in the cookie (one downside: safety, showed the whole world about server IP). So again, can store a random number/hashed value on Load Balancer. It shows which serverID to hit once revisiting. Remember which back-end server to send cookie to. +- Caching: + file-based caching approach: send .html out. + down-side: 1. space. 2. old generated files are really hard to change. + mysqul-query cashed: for identical sql request + memcached: store in memory of the idetical query. Like a table. store . + next time when checking, try look up key. + Down-side: run out of ram. Solution: LRUCahe, remove old records(double-linked-list) + +- Replication: + Master && multiple Slaves + advantage: 1. Same request/query will be paste to all slaves, so master fail, just put up one salve; 2. If READ heavy, they are redundant server to lots readings. + disadvantage: + Must have at least load balancer: that is one-point-failure if just one load balancer + +- Partitioning: + based on user informaiton, like name. Put common user (same last name) into certain servers. + +- Bottleneck: data traffice and data storage +- +------Example +- 1:26:00 of the video (http://www.hiredintech.com/system-design/scalability-fundamentals/) +We have backend web server +Sticky session: use cookie and store server ID +Use load balancer that two web server connects: +Use load balancer to link to the two master db: + Two master db that talks to each other: master-master replication +Now we need 2 load balancer to prevent one-point-failure at the webServer-db connection. +Now we also need 2 load balancers at the (which web server to hit) level, that is another 1-pointer-failure +Switch for the complex connections: + Now we have so many connections: we need switches to handle the connections. + We need at least two ports on each device to: go to the correct switch. Becareful with loop. +- Eventually we will handle: (1:34:00) + Scalibility + Redundancy + High probablity of up time + Resolution against failure + +- Another big issue: + What is ISP goes down? The whole package mentioned above go down? + Amazon solution, another ISP, called avalibility zone: like west, asia, south american. + How to distribute IP on different data center? Load Balancer at the DNS level, global Load Balancer. (Note, if in one building, could be staying at this building) + Well, if a building is gone, once your TTL(Time to live) is expired, you will be re-route to another ISP building. + +- Before getting into building: + Firewall, only a few ports are open: like tcp80, 443, 22 (ssh) + can allow https before first load balancer inside building, and decrypt it after first load balancer + at db lever, only 3306 is allowed. +Reason to lock, for example, 3306 not allowed at entering building? Because no one needs to inject query to db from outside of building; sql query usually only need to be done within the building, so lock the building up, don't allow bad sql injection : ) + + +### URL convention Example Final (http://www.hiredintech.com/system-design/final-thoughts/) +- simple rules: + Always start a single machine + Benchmark the bottle necks, where it indroduces complexity. (No need to add extra complexity) + Think about the questions like: why sql vs. non-sql? + +- Scalable design: + 1. Application, web server, handle requests/traffic + * start with 1 server + * it's better to measure the spark traffic (highest we get) + * add load balancer, and a cluster of servers. (could use amazon elastic load balancer, to automatically add more servers) + + 2. Data Storage + 1) Billions of object, 2) each object is small, 3) no relationship between object, 4) read 9x more than write (360read/s, 40writes/s), 5) 3TB urls, 36GB of hashes + We can use sql or non-sql + In example, go with MySQL + widely used + Mature tech + Clear scaling paradiams(sharding, master/slave replication, master/master replication) + Used by fb, twitter, google. + * index lookups are very fast (as fast as non-sql) + mappings: + hash: varchar(6) + original_url: varchar(512) + + Over years, it holds 3TB data. Storage-wise, it's okay. However, how to serve up quickly? + + * First, Use one MySQL table with two varchar fields + * Create uinique index on the hash(36GB+). We want to hold it in memory. However, we need to look up fast. + * For 1st stemp, vertical scaling of the MySQL machine, adding more RAM (nowadays ram are cheaper too : ) + * Eventually need to partition the data, into 5 partitions: 600GB of data, 8GB of indexes on each machine. (Partitioning early on, it helps to scale later, just add more nodes) + * One day, if read/write are super different, Master-Slave, ... + write to master, and read from slaves. + +## Design UBER +1. Requirements + Same requirements between user && driver: GPS tracking, detect pickup/drop off, cost calculation + Design a web app (or mobile app) for end user to make/cancel car reservation, make payment, rate driver. + Design a web app (or mobile app) for driver to accept/decline car reservation, accept payment, rate passenger. + Extra features beyond basics: car pool, split cost, rush-hour rate calculation. + +2. Identify the end systems: + Backend server that handles communication, data tracking, payment trasaction...etc + Passenger user app + Driver user app + +3. Inputs and outputs of each end system: + **Server should store every piece of information received or change to database during this process** + Server-input: + * Passenger create account, login, log off + * Driver create account, login, log off + * Passenger/Driver payment information + * driver locations + * passenger locations + * GPS location data before && during the trip + * request to pair driver && passenger + * request to start trip + * request to end trip + * request to drop reservation from driver + * request to drop reservation from passenger + * request to calculate cost per trip + * accept rating, comment, report ... + + Server-output: + * ack passenger account generation, login, logoff + * ack driver account generation, login, logoff + * ack driver/passenger payment info and store to db + * broadcast driver locations to passenger + * broadcast passenger locations to driver + * response pair confirmation to driver && passenger with contact information of driver&&passenger + * start a trip between driver && passenger + * end a trip between driver && passenger + * calculate recommended route and send to driver&&passenger + * response reservation dropped from driver with panelty + * response reservation dropped from passenger with panelty + * response cost calculated to passenger and intiate payment charge to passenger + * response cost calculated to driver and initiate payment to driver + * store rating, comment, report into database. Trigger messages to coresponding party. + + Passenger-input: data that passenger receives + * ack of login and ready to pick driver + * status of drivers around current location + * auto-matched driver and related information about driver, car condition, price rate + * confirmation of car reservation with driver's info + * trip route and estimated time + * GPS tracking of car arriving or GPS tracking during the trip + * notification of payment + * notification of canceled trip + * prompt to rate and comment + * phone call from driver (extenal) + + Passenger-output: action that passenger takes + * create account + * login + * add payment information + * put current location and destination location + * select type of uber car, and start searching(matching) + * accept/decline auto-matched driver + * call driver (extenal) + * cancel reservation + * put comment, rating, or report to the system + * automatically pay (be charged) of the trip cost from server + + Driver-input: + * ack of login and ready to start driving + * auto-recommended passenger's information: location, passenger rating + * confirmation of reservation && current waiting location + * trip route and estimated time + * GPS tracking of car arriving or GPS tracking during the trip + * notification of payment + * notification of trip cancelation from passenger + * prompt to rate and comment passenger + * phone call from passenger (extenal) + * receive payment from server + + Driver-output: + * create account + * login and set status avaialbe + * add payment info + * accept/decline recommended match + * call passenger (extenal) + * cancel reservation + * put comment && rating of passenger + + +4. Summarize core features and tools to implement + * account management: + * payment integration: paypal integration? some other credicar processing tools + * matching algorithm: core problem to solve. Figure out the cheapest match for passenger, and time&&cost efficient match for driver. There might be lots of constraints to think about for the matching algorithm: cost&&time to pick up passenger around multiple driver, based on driver preference to filter type of trip (farest distance to travel) + * trip process monitoring, notification: RESTful calls between server && driver && passenger. + * GPS location tracking and route calculation: Google map? + * trip cost calculation: calculated based on route length, trip time, rate at specific time, complains filed by passenger + * rating && comment system: RESTful post from driver/passenger + +5. Technologies potentially needed: + Tools:A server to handle RESTful calls, support live connection between nodes, handle trip matching algorithm, handle cost calculation. + * Node.js with expressJS: provide RESTful API + * Socket.io for concurrent communication between server, user, driver in the same socket room. + * Data storag: Sql or non-sql? Why? Later on, it seems easy to split data by region, so non-sql db seems okay to use. + * Algorithm: How does heavy calculation handled on Nodejs? Should it be something to do with multi-threading? + +6. How does the system scale? What are the limits and trade-off in current design? What improvmenet can be done to design it differently? + First, assume everything is running based off one giant server: all conversations and calculation are handled via this server. + Second, the size of data might be too costly to search, calculate, and it's not practical to store everything on one machine: + * user/driver account info might be too large + * concurrent calculation for trip matching + * number concurrent trip monitoring and conversation + * concurrent calculation for trip cost + Therefore, it seems wiser to split onto multiple servers. + Third question: in which way to split the data? It seems we need to treat different type of data separately + * For actively moving driver and user: we can store their location data dynamically by region. Once moved into/out of one regin, poll the information from one server into another server. Here, it's wise to use HashTable to store as . Calculation algorithm may also happen on this server, because both driver && passenger are on this server, defined by region. + * Now we've splitted data into servers by region. However, for same region, it might be too much work for one machine. We need to split data aross different machines for same region. Here, use another Hash lookup table to store to split data into even smaller sections to fit in different server. Now we can have more **regionServer**. + * A improvement that can be done: for relative static information account,payment,rating, they are only used once or twice during a trip. It might be okay to store these information on a type of server that specifically handles account look up, let's call it **accountServer**. Again, there might be too much account info to store, we can build lookup tables to store . Double again, do MapReduce to hash the keys so that we can split the look up table if the table is too big to store on one server. diff --git a/WordPress.txt b/WordPress.txt index 4e01b35..fe06671 100644 --- a/WordPress.txt +++ b/WordPress.txt @@ -1,2 +1,2 @@ -Java Solutions to problems from LintCode(http://LintCode.com). -
#Problem      Level  Language
02 Sum.javaJava
13 Sum Closest.javaJava
23 Sum.javaJava
34 Sum.javaJava
4A+B.javaJava
5Add Binary.javaJava
6Anagrams.javaJava
7Backpack.javaJava
8Balanced Binary Tree.javaJava
9Best Time to Buy and Sell Stock I.javaJava
10Best Time to Buy and Sell Stock II.javaJava
11Best Time to Buy and Sell Stock III .javaJava
12Binary Representation.javaJava
13Binary Search.javaJava
14Binary Tree Level Order Traversal II.javaJava
15Binary Tree Level Order Traversal.javaJava
16Binary Tree Maximum Path Sum.javaJava
17Binary Tree Preorder Traversal.javaJava
18Binary Tree Zigzag Level Order Traversal.javaJava
19BinaryTreeInorderTraversal.javaJava
20BinaryTreePostorderTraversal.javaJava
21Climbing Stairs.javaJava
22Clone Graph.javaJava
23Combination Sum II.javaJava
24Combination Sum.javaJava
25Combinations.javaJava
26Compare Strings.javaJava
27Construct Binary Tree from Inorder and Postorder Traversal.javaJava
28Construct Binary Tree from Inorder and Preorder Traversal.javaJava
29Convert Integer A to Integer B.javaJava
30Convert Sorted Array to Binary Search Tree With Minimal Height.javaJava
31Convert Sorted List to Binary Search Tree.javaJava
32Copy List with Random Pointer.javaJava
33Count 1 in Binary.javaJava
34Count and Say.javaJava
35Delete Digits.javaJava
36Delete Node in the Middle of Singly Linked List.javaJava
37Distinct Subsequences.javaJava
38Easy Reverse Linked List.javaJava
39Edit Distance.javaJava
40Fast Power.javaJava
41Fibonacci.javaJava
42Find a Peak.javaJava
43Find Minimum in Rotated Sorted Array II.javaJava
44Find Minimum in Rotated Sorted Array.javaJava
45Find the Connected Component in the Undirected Graph.javaJava
46First Bad Version.javaJava
47First Missing Positive.javaJava
48Gas Station.javaJava
49Hash Function.javaJava
50Implement Queue by Two Stacks.javaJava
51Insert Interval.javaJava
52Insert Node in a Binary Search Tree .javaJava
53Insertion Sort List.javaJava
54Interleaving String.javaJava
55Invert Binary Tree.javaJava
56Jump Game II.javaJava
57Jump Game.javaJava
58Kth Largest Element.javaJava
59Largest Number.javaJava
60Largest Rectangle in Histogram.javaJava
61Length of Last Word.javaJava
62Linked List Cycle.javaJava
63Longest Common Prefix.javaJava
64Longest Common Subsequence.javaJava
65Longest Common Substring.javaJava
66Longest Consecutive Sequence.javaJava
67Longest Increasing Continuous subsequence.javaJava
68Longest Words.javaJava
69Lowest Common Ancestor.javaJava
70Majority Number II.javaJava
71Majority Number III.javaJava
72Majority Number.javaJava
73Maximum Depth of Binary Tree.javaJava
74Maximum Product Subarray.javaJava
75MaximumSubarray.javaJava
76MaximumSubarrayII.javaJava
77Median.javaJava
78Merge Intervals.javaJava
79Merge k Sorted Lists.javaJava
80Merge Sorted Array .javaJava
81Merge Sorted Array II.javaJava
82Merge Two Sorted List.javaJava
83Min Stack.javaJava
84Minimum Path Sum.javaJava
85Minimum Subarray.javaJava
86Minimum Window Substring.javaJava
87MinimumDepthOfBinaryTree.javaJava
88Next Permutation.javaJava
89NQueens.javaJava
90NQueensII.javaJava
91Nth to Last Node in List.javaJava
92Number of Islands.javaJava
93Number Triangles.javaJava
94O(1) Check Power of 2.javaJava
95Palindrome Partitioning II.javaJava
96Palindrome Partitioning.javaJava
97Partition Array by Odd and Even.javaJava
98Partition Array.javaJava
99Partition List.javaJava
100Permutations.javaJava
101Plus One.javaJava
102Product of Array Exclude Itself.javaJava
103Recover rotated array.javaJava
104Rehashing.javaJava
105Remove Duplicates from Sorted Array.javaJava
106Remove Duplicates from Sorted List II.javaJava
107Remove Duplicates from Sorted List.javaJava
108Remove Node in Binary Search Tree.javaJava
109Remove Nth Node From End of List.javaJava
110Reorder List.javaJava
111Reverse Integer.javaJava
112Reverse Linked List II .javaJava
113Reverse Words in a String.javaJava
114Rotate List.javaJava
115Rotate String.javaJava
116Search a 2D Matrix II.javaJava
117Search a 2D Matrix.javaJava
118Search for a Range.javaJava
119Search Insert Position.javaJava
120Search Range in Binary Search Tree .javaJava
121Search Rotated Sorted Array II.javaJava
122Search Rotated Sorted Array.javaJava
123Serilization and Deserialization Of Binary Tree.javaJava
124Single Number II.javaJava
125Single Number III.javaJava
126Single Number.javaJava
127Singleton.javaJava
128Sort Color.javaJava
129Sort Colors II.javaJava
130Sort Letters by Case.javaJava
131Sort List.javaJava
132Space Replacement.javaJava
133Sqrt(x).javaJava
134String to Integer(atoi).javaJava
135StrStr.javaJava
136Subarray Sum Closest.javaJava
137Subarray Sum.javaJava
138Subset.javaJava
139Subtree.javaJava
140Topological Sorting.javaJava
141Trailing Zeros.javaJava
142Two Lists Sum.javaJava
143Two Strings Are Anagrams.javaJava
144Ugly Number.javaJava
145Unique Binary Search Tree II.javaJava
146Unique Binary Search Tree.javaJava
147Unique Path.javaJava
148Unique Paths II.javaJava
149Unique Permutations.javaJava
150Unique Subset.javaJava
151Update Bits.javaJava
152Validate Binary Search Tree.javaJava
153Wood Cut.javaJava
154Word Break.javaJava
155Word Ladder II.javaJava
156Word Ladder.javaJava
157Word Search II.javaJava
158Word Search.javaJava
\ No newline at end of file +Java Solutions to algorithm problems from LintCode, LeetCode...etc. +
#Problem Level Language
02 Sum II - Input array is sorted.javaJava
12 Sum II.javaJava
22 Sum.javaJava
33 Sum Closest.javaJava
43 Sum Smaller.javaJava
53 Sum.javaJava
64 Sum.javaJava
7A+B.javaJava
8Add and Search Word.javaJava
9Add Binary.javaJava
10Add Two Numbers II.javaJava
11Add Two Numbers.javaJava
12Alien Dictionary.javaJava
13Anagrams.javaJava
14Backpack II.javaJava
15Backpack.javaJava
16Balanced Binary Tree.javaJava
17Best Time to Buy and Sell Stock I.javaJava
18Best Time to Buy and Sell Stock II.javaJava
19Best Time to Buy and Sell Stock III .javaJava
20Best Time to Buy and Sell Stock IV.javaJava
21Binary Representation.javaJava
22Binary Search Tree Iterator.javaJava
23Binary Tree Inorder Traversal.javaJava
24Binary Tree Level Order Traversal II.javaJava
25Binary Tree Level Order Traversal.javaJava
26Binary Tree Longest Consecutive Sequence.javaJava
27Binary Tree Maximum Path Sum II.javaJava
28Binary Tree Maximum Path Sum.javaJava
29Binary Tree Path Sum.javaJava
30Binary Tree Paths.javaJava
31Binary Tree Postorder Traversal.javaJava
32Binary Tree Preorder Traversal.javaJava
33Binary Tree Right Side View.javaJava
34Binary Tree Serialization.javaJava
35Binary Tree Zigzag Level Order Traversal.javaJava
36Building Outline.javaJava
37Burst Balloons.javaJava
38Change to Anagram.javaJava
39Classical Binary Search.javaJava
40Climbing Stairs.javaJava
41Clone Graph.javaJava
42Closest Binary Search Tree Value.javaJava
43Closest Number in Sorted Array.javaJava
44Coins in a Line.javaJava
45ColorGrid.javaJava
46Combination Sum II.javaJava
47Combination Sum.javaJava
48Combinations.javaJava
49Compare Strings.javaJava
50Complete Binary Tree.javaJava
51Construct Binary Tree from Inorder and Postorder Traversal.javaJava
52Construct Binary Tree from Inorder and Preorder Traversal.javaJava
53Container With Most Water.javaJava
54Convert Binary Search Tree to Doubly Linked List.javaJava
55Convert Expression to Polish Notation.javaJava
56Convert Expression to Reverse Polish Notation.javaJava
57Convert Integer A to Integer B.javaJava
58Convert Sorted Array to Binary Search Tree With Minimal Height.javaJava
59Convert Sorted List to Binary Search Tree.javaJava
60Copy List with Random Pointer.javaJava
61Cosine Similarity.javaJava
62Count 1 in Binary.javaJava
63Count and Say.javaJava
64Count of Smaller Number before itself.javaJava
65Count of Smaller Number.javaJava
66Count Primes.javaJava
67Course Schedule II.javaJava
68Course Schedule.javaJava
69Data Stream Median.javaJava
70Delete Digits.javaJava
71Delete Node in the Middle of Singly Linked List.javaJava
72Distinct Subsequences.javaJava
73Edit Distance.javaJava
74Encode and Decode Strings.javaJava
75ExcelSheetColumnNumber .javaJava
76Expression Evaluation.javaJava
77Expression Tree Build.javaJava
78Fast Power.javaJava
79Fibonacci.javaJava
80Find Minimum in Rotated Sorted Array II.javaJava
81Find Minimum in Rotated Sorted Array.javaJava
82Find Peak Element II.javaJava
83Find Peak Element.javaJava
84Find the Connected Component in the Undirected Graph.javaJava
85Find the Weak Connected Component in the Directed Graph.javaJava
86First Bad Version.javaJava
87First Missing Positive.javaJava
88Flatten 2D Vector.javaJava
89Flatten Binary Tree to Linked List.javaJava
90Flattern 2D Vector.javaJava
91Flip Game II.javaJava
92Flip Game.javaJava
93Fraction to Recurring Decimal.javaJava
94Game of Life.javaJava
95Gas Station.javaJava
96Generate Parentheses.javaJava
97Graph Valid Tree.javaJava
98Gray Code.javaJava
99Group Anagrams.javaJava
100Group Shifted Strings.javaJava
101H-Index II.javaJava
102H-Index.javaJava
103Happy Number.javaJava
104Hash Function.javaJava
105HashHeap.javaJava
106HashWithArray.javaJava
107HashWithCustomizedClass(LinkedList).javaJava
108Heapify.javaJava
109House Robber II.javaJava
110House Robber III.javaJava
111House Robber.javaJava
112Identical Binary Tree.javaJava
113Implement Queue by Two Stacks.javaJava
114Implement Stack by Two Queues.javaJava
115Implement Stack.javaJava
116Implement strStr().javaJava
117Implement Trie (Prefix Tree).javaJava
118Implement Trie.javaJava
119IndexMatch.javaJava
120Inorder Successor in Binary Search Tree.javaJava
121Insert Interval.javaJava
122Insert Node in a Binary Search Tree .javaJava
123Insertion Sort List.javaJava
124Integer to English Words.javaJava
125Interleaving Positive and Negative Numbers.javaJava
126Interleaving String.javaJava
127Intersection of Two Linked Lists.javaJava
128Interval Minimum Number.javaJava
129Interval Sum II.javaJava
130Interval Sum.javaJava
131Invert Binary Tree.javaJava
132Isomorphic Strings.javaJava
133Jump Game II.javaJava
134Jump Game.javaJava
135Kth Largest Element.javaJava
136Kth Smallest Element in a BST.javaJava
137Kth Smallest Number in Sorted Matrix.javaJava
138Kth Smallest Sum In Two Sorted Arrays.javaJava
139Largest Number.javaJava
140Largest Rectangle in Histogram.javaJava
141Last Position of Target.javaJava
142Length of Last Word.javaJava
143Letter Combinations of a Phone Number.javaJava
144Linked List Cycle II.javaJava
145Linked List Cycle.javaJava
146Longest Common Prefix.javaJava
147Longest Common Subsequence.javaJava
148Longest Common Substring.javaJava
149Longest Consecutive Sequence.javaJava
150Longest Increasing Continuous subsequence II.javaJava
151Longest Increasing Continuous subsequence.javaJava
152Longest Increasing Subsequence.javaJava
153Longest Palindromic Substring.javaJava
154Longest Substring with At Most K Distinct Characters.javaJava
155Longest Substring Without Repeating Characters.javaJava
156Longest Words.javaJava
157Lowest Common Ancestor II.javaJava
158Lowest Common Ancestor of a Binary Search Tree.javaJava
159Lowest Common Ancestor.javaJava
160LRU Cache.javaJava
161Majority Number II.javaJava
162Majority Number III.javaJava
163Majority Number.javaJava
164Matrix Zigzag Traversal.javaJava
165Max Tree.javaJava
166Maximal Square.javaJava
167Maximum Depth of Binary Tree.javaJava
168Maximum Product Subarray.javaJava
169Maximum Subarray III.javaJava
170MaximumSubarray.javaJava
171MaximumSubarrayII.javaJava
172Median of two Sorted Arrays.javaJava
173Median.javaJava
174Meeting Rooms II.javaJava
175Meeting Rooms.javaJava
176Merge Intervals.javaJava
177Merge k Sorted Arrays.javaJava
178Merge k Sorted Lists.javaJava
179Merge Sorted Array II.javaJava
180Merge Sorted Array.javaJava
181Merge Two Sorted List.javaJava
182Merge Two Sorted Lists.javaJava
183Middle of Linked List.javaJava
184Min Stack.javaJava
185Minimum Height Trees.javaJava
186Minimum Path Sum.javaJava
187Minimum Size Subarray Sum.javaJava
188Minimum Subarray.javaJava
189Minimum Window Substring.javaJava
190MinimumDepthOfBinaryTree.javaJava
191Missing Ranges.javaJava
192Multiply Strings.javaJava
193Next Permutation.javaJava
194Nim Game.javaJava
195NQueens.javaJava
196NQueensII.javaJava
197Nth to Last Node in List.javaJava
198Number of Airplane in the sky.javaJava
199Number of Islands II.javaJava
200Number of Islands.javaJava
201Number Triangles.javaJava
202O(1) Check Power of 2.javaJava
203One Edit Distance.javaJava
204Paint Fence.javaJava
205Palindrome Linked List.javaJava
206Palindrome Partitioning II.javaJava
207Palindrome Partitioning.javaJava
208Palindrome Permutation II.javaJava
209Palindrome Permutation.javaJava
210Partition Array by Odd and Even.javaJava
211Partition Array.javaJava
212Partition List.javaJava
213Pascal's Triangle II.javaJava
214Peeking Iterator.javaJava
215Perfect Squares.javaJava
216Permutation Index.javaJava
217Permutation Sequence.javaJava
218Permutations II.javaJava
219Permutations.javaJava
220Plus One.javaJava
221Populating Next Right Pointers in Each Node II.javaJava
222Populating Next Right Pointers in Each Node.javaJava
223Pow(x,n).javaJava
224Power of Three.javaJava
225Product of Array Exclude Itself.javaJava
226QuickSort.javaJava
227Recover Rotated Sorted Array.javaJava
228Rehashing.javaJava
229Remove Duplicates from Sorted Array.javaJava
230Remove Duplicates from Sorted List II.javaJava
231Remove Duplicates from Sorted List.javaJava
232Remove Duplicates from Unsorted List.javaJava
233Remove Linked List Elements.javaJava
234Remove Node in Binary Search Tree.javaJava
235Remove Nth Node From End of List.javaJava
236Reorder List.javaJava
237Restore IP Addresses.javaJava
238Reverse Integer.javaJava
239Reverse Linked List II .javaJava
240Reverse Linked List.javaJava
241Reverse Words in a String II.javaJava
242Reverse Words in a String.javaJava
243reverseInteger.javaJava
244Roman to Integer.javaJava
245Rotate Image.javaJava
246Rotate List.javaJava
247Rotate String.javaJava
248Search a 2D Matrix II.javaJava
249Search a 2D Matrix.javaJava
250Search for a Range.javaJava
251Search Insert Position.javaJava
252Search Range in Binary Search Tree .javaJava
253Search Rotated in Sorted Array II.javaJava
254Search Rotated in Sorted Array.javaJava
255Segment Tree Build II.javaJava
256Segment Tree Build.javaJava
257Segment Tree Modify.javaJava
258Segment Tree Query II.javaJava
259Segment Tree Query.javaJava
260Serilization and Deserialization Of Binary Tree.javaJava
261Single Number II.javaJava
262Single Number III.javaJava
263Single Number.javaJava
264Singleton.javaJava
265Sliding Window Maximum.javaJava
266Sliding Window Median.javaJava
267Sort Color.javaJava
268Sort Colors II.javaJava
269Sort Letters by Case.javaJava
270Sort List.javaJava
271Space Replacement.javaJava
272Sqrt(x).javaJava
273Stone Game.javaJava
274String to Integer(atoi).javaJava
275Strobogrammatic Number II.javaJava
276Strobogrammatic Number.javaJava
277StrStr.javaJava
278Subarray Sum Closest.javaJava
279Subarray Sum.javaJava
280Subset.javaJava
281Subsets II.javaJava
282Subtree.javaJava
283Summary Ranges.javaJava
284Surrounded Regions.javaJava
285Swap Nodes in Pairs.javaJava
286Symmetric Binary Tree.javaJava
287The Smallest Difference.javaJava
288Top K Frequent Words.javaJava
289Topological Sorting.javaJava
290Total Occurrence of Target.javaJava
291Trailing Zeros.javaJava
292Trapping Rain Water II.javaJava
293Trapping Rain Water.javaJava
294Triangle Count.javaJava
295Tweaked Identical Binary Tree.javaJava
296Two Lists Sum.javaJava
297Two Strings Are Anagrams.javaJava
298Ugly Number II.javaJava
299Ugly Number.javaJava
300Unique Binary Search Tree II.javaJava
301Unique Binary Search Tree.javaJava
302Unique Characters.javaJava
303Unique Path.javaJava
304Unique Paths II.javaJava
305Unique Word Abbreviation.javaJava
306Update Bits.javaJava
307Valid Anagram.javaJava
308Valid Palindrome.javaJava
309Valid Parentheses.javaJava
310Valid Sudoku.javaJava
311Validate Binary Search Tree.javaJava
312Wiggle Sort.javaJava
313Wood Cut.javaJava
314Word Break II.javaJava
315Word Break.javaJava
316Word Ladder II.javaJava
317Word Ladder.javaJava
318Word Pattern.javaJava
319Word Search II.javaJava
320Word Search.javaJava
321Zigzag Iterator.javaJava
\ No newline at end of file diff --git a/knowledgeHash.json b/knowledgeHash.json old mode 100644 new mode 100755 index 2d358d4..41da2c5 --- a/knowledgeHash.json +++ b/knowledgeHash.json @@ -1,4 +1,4 @@ -//https://github.com/shawnfan/LintCode/blob/master/Java/ +//https://github.com/awangdev/LintCode/blob/master/Java/ /* //Format: "name" : { @@ -169,7 +169,13 @@ "which of these points are in a given interval" ], "problems" : [ - "", + "Segment Tree Query", + "Segment Tree Modify", + "Segment Tree Build", + "Interval Sum", + "Interval Minimum Number", + "Count of Smaller Number", + "Count of Smaller Number before itself", ] }, "Expression Tree" : { @@ -262,6 +268,24 @@ "", ] }, + "Scan Line" : { + "nickname": "扫描线", + "property" : [ + "把Interval分拆成Point{x,flag}.起点flag=1,终点flag=-1", + "用PriorityQueue可以sort这些点", + "维持一个count来判断同时又几个meeting在开,需要多少房间;一个人同时能参加所有meeting嘛,需要不重合", + "天上多少飞机同时在飞", + "根据count的情况merge interval, insert interval", + "在扫描时候,一定注意PriorityQueue里面在同一个point.x的很多点,可能同时发生,要全部处理完才能move on", + ], + "problems" : [ + "Meeting Rooms", + "Meeting Rooms II", + "Merge Intervals", + "Insert Interval", + "Planes in sky", + ] + }, "Math" : { "nickname": "数学", "property" : [