├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradlew ├── gradlew.bat └── src └── main └── java ├── boggle_game └── BoggleGame.java ├── collatz_conjecture └── CollatzConjecture.java ├── common ├── Interval.java ├── NestedInteger.java ├── Trie.java └── TrieNode.java ├── connect_four └── ConnectFour.java ├── csv_parser └── CSVParser.java ├── display_page └── DisplayPage.java ├── file_system └── FileSystem.java ├── find_case_combinations_of_a_string └── FindCaseCombinationsofaString.java ├── find_median_in_large_file_of_integers └── FindMedianinLargeIntegerFileofIntegers.java ├── finding_ocean └── FindingOcean.java ├── guess_number └── GuessNumber.java ├── hilbert_curve └── HilbertCurve.java ├── implement_queue_with_fixed_size_of_arrays └── ImplementQueuewithFixedSizeofArrays.java ├── ip_range_to_cidr └── IPRangetoCIDR.java ├── k_edit_distance └── KEditDistance.java ├── list_of_list_iterator └── ListofListIterator.java ├── maximum_number_of_nights_you_can_accommodate └── MaximumNumberofNightsYouCanAccommodate.java ├── meeting_time └── MeetingTime.java ├── menu_combination_sum └── MenuCombinationSum.java ├── minimum_cost_with_at_most_k_stops └── MinimumCostwithAtMostKStops.java ├── minimum_vertices_to_traverse_directed_graph └── MinimumVerticestoTraverseDirectedGraph.java ├── number_of_intersected_rectangles └── NumberofIntersectedRectangles.java ├── palindrome_pairs └── PalindromePairs.java ├── preference_list └── PreferenceList.java ├── regular_expression └── RegularExpression.java ├── round_prices └── RoundPrices.java ├── simulate_diplomacy └── SimulateDiplomacy.java ├── sliding_game └── SlidingGame.java ├── string_pyramids_transition_matrix └── StringPyramidsTransitionMatrix.java ├── ten_wizards └── TenWizards.java ├── travel_buddy └── TravelBuddy.java └── water_land └── WaterLand.java /.gitignore: -------------------------------------------------------------------------------- 1 | # gradle/build/.class files 2 | .gradle/* 3 | gradle/* 4 | build/ 5 | *.class 6 | 7 | # Log file 8 | *.log 9 | 10 | # BlueJ files 11 | *.ctxt 12 | 13 | # Mobile Tools for Java (J2ME) 14 | .mtj.tmp/ 15 | 16 | # Package Files # 17 | *.jar 18 | *.war 19 | *.ear 20 | *.zip 21 | *.tar.gz 22 | *.rar 23 | 24 | # Intellij related 25 | .idea/* 26 | *.iml 27 | 28 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 29 | hs_err_pid* 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Daniel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AirBnB Interview Questions 2 | 3 | ## Disclaim 4 | 5 | All questions below are collected from Internet, which include but not limit to: 6 | 7 | * [GeeksForGeeks](http://www.geeksforgeeks.org/company-preparation/) 8 | * [GlassDoor](https://www.glassdoor.com/Interview/san-francisco-airbnb-interview-questions-SRCH_IL.0,13_IC1147401_KE14,20.htm) 9 | 10 | From what I know: 11 | * AirBnB is not hiring during this coronavirus pandemic time. 12 | * airBnB likely will change all interview questions after they start to hire on 2021. 13 | This repository is no longer updated. 14 | 15 | ## List of Questions 16 | 17 | #### 1 [Collatz Conjecture](https://en.wikipedia.org/wiki/Collatz_conjecture) 18 | 19 | * If a number is odd, the next transform is 3*n+1 20 | * If a number is even, the next transform is n/2 21 | * The number is finally transformed into 1. 22 | * The step is how many transforms needed for a number turned into 1. 23 | 24 | Given an integer n, output the max steps of transform number in [1, n] into 1. 25 | 26 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/collatz_conjecture/CollatzConjecture.java) 27 | 28 | #### 2 [Implement Queue with Limited Size of Array](https://www.cs.bu.edu/teaching/c/queue/array/types.html) 29 | 30 | Implement a queue with a number of arrays, in which each array has fixed size. 31 | 32 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/implement_queue_with_fixed_size_of_arrays/ImplementQueuewithFixedSizeofArrays.java) 33 | 34 | #### 3 List of List Iterator 35 | 36 | Given an array of arrays, implement an iterator class to allow the client to traverse 37 | and remove elements in the array list. 38 | 39 | This iterator should provide three public class member functions: 40 | 41 | * boolean hasNext() return true if there is another element in the set 42 | * int next() return the value of the next element in the array 43 | * void remove() remove the last element returned by the iterator. That is, remove the element that the previous next() returned. This method can be called only once per call to next(), otherwise an exception will be thrown. 44 | 45 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/list_of_list_iterator/ListofListIterator.java) 46 | 47 | #### 4 Display Page (Pagination) 48 | 49 | Given an array of CSV strings representing search results, output results sorted by a score initially. A given host may have several listings that show up in these results. Suppose we want to show 12 results per page, but we don’t want the same host to dominate the results. 50 | 51 | Write a function that will reorder the list so that a host shows up at most once on a page if possible, but otherwise preserves the ordering. Your program should return the new array and print out the results in blocks representing the pages. 52 | 53 | Given an array of csv strings, output results separated by a blank line. 54 | 55 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/display_page/DisplayPage.java) 56 | 57 | #### 5 Travel Buddy 58 | 59 | I have a wish list of cities that I want to visit to, my friends also have city wish lists that they want to visit to. If one of my friends share more than 50% (over his city count in his wish list), he is my buddy. 60 | 61 | Given a list of city wish list, output buddy list sorting by similarity. 62 | 63 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/travel_buddy/TravelBuddy.java) 64 | 65 | #### 6 File System 66 | 67 | Write a file system class, which has two functions: create, and get 68 | * create("/a",1) 69 | * get("/a") //get 1 70 | * create("/a/b",2) 71 | * get("/a/b") //get 2 72 | * create("/c/d",1) //Error, because "/c" is not existed 73 | * get("/c") //Error, because "/c" is not existed 74 | 75 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/file_system/FileSystem.java) 76 | 77 | #### 7 [Palindrome Pairs](https://leetcode.com/problems/palindrome-pairs/description/) 78 | 79 | Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome. 80 | 81 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/palindrome_pairs/PalindromePairs.java) 82 | 83 | #### 8 Find Median in Large Integer File of Integers 84 | 85 | Find the median from a large file of integers. You can not access the numbers by index, can only access it sequentially. And the numbers cannot fit in memory. 86 | 87 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/find_median_in_large_file_of_integers/FindMedianinLargeIntegerFileofIntegers.java) 88 | 89 | #### 9 [IP Range to CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) 90 | 91 | Given an IPv4 IP address p and an integer n, return a list of CIDR strings that most succinctly represents the range of IP addresses from p to (p + n). 92 | 93 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/ip_range_to_cidr/IPRangetoCIDR.java) 94 | 95 | #### 10 [CSV Parser](http://creativyst.com/Doc/Articles/CSV/CSV01.htm#EmbedBRs) 96 | 97 | Write a method to parse input string in CSV format. 98 | 99 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/csv_parser/CSVParser.java) 100 | 101 | #### 11 [Text Justification](https://leetcode.com/problems/text-justification/description/) 102 | 103 | Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified. 104 | 105 | You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters. 106 | 107 | Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right. 108 | 109 | For the last line of text, it should be left justified and no extra space is inserted between words. 110 | 111 | #### 12 Regular Expression 112 | 113 | Implement a simple regex parser which, given a string and a pattern, returns a boolean indicating whether the input matches the pattern. 114 | 115 | By simple, we mean that the regex can only contain special character: 116 | 117 | * \* (star) The star means what you'd expect, that there will be zero or more of previous character in that place in the pattern. 118 | * . (dot) The dot means any character for that position. 119 | * \+ (plus). The plus means one or more of previous character in that place in the pattern. 120 | 121 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/regular_expression/RegularExpression.java) 122 | 123 | #### 13 Water Drop/Water Land/Pour Water 124 | 125 | Input is a array represent how the height of water is at each position, the number of water will be poured, and the pour position. 126 | Print the land after all water are poured. 127 | 128 | Example: 129 | input land height int[]{5,4,2,1,3,2,2,1,0,1,4,3} 130 | The land is looks ike: 131 | 132 | ```text 133 | + 134 | ++ + 135 | ++ + ++ 136 | +++ +++ ++ 137 | ++++++++ +++ 138 | ++++++++++++ 139 | 012345678901 140 | ``` 141 | 142 | water quantity is 8 and pour at position 5. The land becomes: 143 | 144 | ```text 145 | + 146 | ++ + 147 | ++www+ ++ 148 | +++w+++www++ 149 | ++++++++w+++ 150 | ++++++++++++ 151 | 012345678901 152 | ``` 153 | 154 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/water_land/WaterLand.java) 155 | 156 | #### 14 [Hilbert Curve](https://en.wikipedia.org/wiki/Hilbert_curve) 157 | 158 | Given (x, y, iter), in which (x, y) is position at x-axis and y-axis, and iter is how many iterations will be. Output is in iteration *iter*, how many steps are required to move from (0, 0) to (x, y) in iteration *iter*. 159 | 160 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/hilbert_curve/HilbertCurve.java) 161 | 162 | #### 15 [Simulate Diplomacy](http://www.backstabbr.com/rules) 163 | 164 | Input (army_name, location, action()) 165 | 166 | action() could be: 167 | * move(new_location) then army_name to new_location, If there is an army at new_location, then company strength of two aramy: 168 | * The army have higher strength stay at new_location, the lower army is disappeared. 169 | * If two army have the same strength, both are disppeared. 170 | * hold() stay at the same location 171 | * support(army_name) supoort another army. The supported army have one more strength. 172 | 173 | The army's strength are intialized as the same. 174 | 175 | ### 16 Meeting Time 176 | 177 | Input is a number of meetings (start_time, end_time)。 178 | Output is a number of time intervals (start_time, end_time), where there is no meetings. 179 | 180 | For exmaple, input is [[1, 3], [6, 7]], [[2, 4]],
[[2, 3], [9, 12]] ] 181 | 182 | output [[4, 6], [7, 9]] 183 | 184 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/meeting_time/MeetingTime.java) 185 | 186 | #### 17 Round Prices 187 | 188 | Given an array of numbers A = [x1, x2, ..., xn] and T = Round(x1+x2+... +xn). We want to find a way to round each element in A such that after rounding we get a new array B = [y1, y2, ...., yn] such that y1+y2+...+yn = T where yi = Floor(xi) or Ceil(xi), ceiling or floor of xi. 189 | 190 | We also want to minimize sum |x_i-y_i| 191 | 192 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/round_prices/RoundPrices.java) 193 | 194 | #### 18 Sliding Game 195 | 196 | You're given a 3x3 board of a tile puzzle, with 8 tiles numbered 1 to 8, and an empty spot. You can move any tile adjacent to the empty spot, to the empty spot, creating an empty spot where the tile originally was. The goal is to find a series of moves that will solve the board, i.e. get [ [1, 2, 3], [4, 5, 6], [7, 8, - ]… 197 | 198 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/sliding_game/SlidingGame.java) 199 | 200 | #### 19 Maximum Number of Nights You Can Accommodate 201 | 202 | Given a set of numbers in an array which represent number of consecutive nights of AirBnB reservation requested, as a host, pick the sequence which maximizes the number of days of occupancy, at the same time, leaving at least 1 day gap in between bookings for cleaning. Problem reduces to finding max-sum of non-consecutive array elements. 203 | 204 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/maximum_number_of_nights_you_can_accommodate/MaximumNumberofNightsYouCanAccommodate.java) 205 | 206 | #### 20 Find Case Combinations of a String 207 | 208 | Find all the combinations of a string in lowercase and uppercase. For example, string "ab" >>> "ab", "Ab", "aB", "AB". So, you will have 2^n (n = number of chars in the string) output strings. The goal is for you to test each of these strings and see if it matchs a hidden string. 209 | 210 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/find_case_combinations_of_a_string/FindCaseCombinationsofaString.java) 211 | 212 | #### 21 Menu Combination Sum 213 | 214 | Given a menu (list of items prices), find all possible combinations of items that sum a particular value K. (A variation of the typical 2sum/Nsum questions). 215 | 216 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/menu_combination_sum/MenuCombinationSum.java) 217 | 218 | #### 22 K Edit Distance 219 | 220 | Find all words from a dictionary that are k edit distance away. 221 | 222 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/k_edit_distance/KEditDistance.java) 223 | 224 | #### 23 Boggle Game 225 | 226 | Given 2d matrix of letters, and a word dictionary, find a path which has largest number of words (existed inside the dictionary). 227 | 228 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/boggle_game/BoggleGame.java) 229 | 230 | #### 24 Minimum Cost with At Most K Stops 231 | 232 | Given a flight itinerary consisting of starting city, destination city, and ticket price (2d list) - find the optimal price flight path to get from start to destination. (A variation of Dynamic Programming Shortest Path) 233 | 234 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/minimum_cost_with_at_most_k_stops/MinimumCostwithAtMostKStops.java) 235 | 236 | #### 25 String Pyramids Transition Matrix 237 | 238 | Given a list of leaf nodes in a pyramid, and a map which indicates what's the possible parent node given a left and right node. Return true if the one of leaf node could turn into the root node, Otherwise, return false. 239 | For example: 240 | 241 | ```text 242 | root 243 | / \ 244 | X X 245 | /\ /\ 246 | X X X 247 | / \/ \/ \ 248 | A B C D 249 | ``` 250 | 251 | Map: 252 | ```text 253 | left: A | B | C | D 254 | right--------------------------------- 255 | A B |A or C| D | A 256 | B D |B or C| A | 257 | C B 258 | D 259 | ``` 260 | Note:1. If left child is B, right child is A, the parent node could be B or C 261 | 262 | Given leaf input of "ABCD", output true. 263 | 264 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/string_pyramids_transition_matrix/StringPyramidsTransitionMatrix.java) 265 | 266 | #### 26 Finding Ocean 267 | 268 | Given: An array of strings where L indicates land and W indicates water, and a coordinate marking a starting point in the middle of the ocean. 269 | 270 | Challenge: Find and mark the ocean in the map by changing appropriate Ws to Os. 271 | * An ocean coordinate is defined to be the initial coordinate if a W, and 272 | * any coordinate directly adjacent to any other ocean coordinate. 273 | 274 | ```text 275 | void findOcean(String[] map, int row, int column); 276 | String[] map = new String[]{ 277 | "WWWLLLW", 278 | "WWLLLWW", 279 | "WLLLLWW" 280 | }; 281 | printMap(map); 282 | ``` 283 | ```text 284 | STDOUT: 285 | WWWLLLW 286 | WWLLLWW 287 | WLLLLWW 288 | ``` 289 | ```text 290 | findOcean(map, 0, 1); 291 | printMap(map); 292 | ``` 293 | ```text 294 | STDOUT: 295 | OOOLLLW 296 | OOLLLWW 297 | OLLLLWW 298 | ``` 299 | 300 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/finding_ocean/FindingOcean.java) 301 | 302 | #### 27 Preference List 303 | 304 | Given a list of everyone's preferred city list, output the city list following the order of everyone's preference order. 305 | 306 | For example, input is [[3, 5, 7, 9], [2, 3, 8], [5, 8]]. One of possible output is [2, 3, 5, 8, 7, 9]. 307 | 308 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/preference_list/PreferenceList.java) 309 | 310 | #### 28 Minimum Vertices to Traverse Directed Graph 311 | 312 | Given a directed grapjh, represented in a two dimension array, output a list of points that can be used to travese every points with the least number of visited vertices. 313 | 314 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/minimum_vertices_to_traverse_directed_graph/MinimumVerticestoTraverseDirectedGraph.java) 315 | 316 | #### 29 10 Wizards 317 | 318 | There are 10 wizards, 0-9, you are given a list that each entry is a list of wizards known by wizard. Define the cost between wizards and wizard as square of different of i and j. To find the min cost between 0 and 9. 319 | 320 | For example: 321 | 322 | wizard[0] list: 1, 4, 5
 323 | 324 | wizard[4] list: 9 325 | 326 | 
wizard 0 to 9 min distance is (0-4)^2+(4-9)^2=41 (wizard[0]->wizard[4]->wizard[9]) 327 | 328 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/ten_wizards/TenWizards.java) 329 | 330 | #### 30 Number of Intersected Rectangles 331 | 332 | Given lots of rectangles, output how many of them intersect. 333 | 334 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/number_of_intersected_rectangles/NumberofIntersectedRectangles.java) 335 | 336 | #### 31 Guess Number 337 | 338 | The system has a secret four digits number, in which each digit is in range of one to 6 [1, 6]. 339 | 340 | Given a four digital number, the system also provide a API that returns the number of correct matched digits. 341 | 342 | Design a method to guess this secret number. 343 | 344 | [Java Source Code](https://github.com/dqi2018/airbnb/blob/master/src/main/java/guess_number/GuessNumber.java) 345 | 346 | 347 | ## Requirements 348 | * Java >= 1.11.106 349 | * Gradle >= 5.6.3 350 | 351 | ## Run Unit Tests 352 | If you write some unit tests, you can use the following command to run them. 353 | 354 | ```bash 355 | # run all tests 356 | gradle test 357 | # run Palindrome Pairs test only 358 | gradle -Dtest.single=PalindromePairs test 359 | # run Palindrome Pairs test only with some informnation 360 | gradle -Dtest.single=PalindromePairs test --info 361 | ``` 362 | 363 | ## Update Logs 364 | v1.0 11/25/2017 365 | * Update almost all questions with unit tests 366 | 367 | v1.1 8/26/2020 368 | * Update build.gradle to be compatible with Java 11 and gradle 5.6 369 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | 5 | sourceCompatibility = "1.11" 6 | targetCompatibility = "1.11" 7 | 8 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' 9 | 10 | eclipse { 11 | classpath { 12 | downloadSources = true 13 | downloadJavadoc = false 14 | } 15 | } 16 | 17 | group = 'allaboutjst' 18 | archivesBaseName = 'airbnb-java-coding' 19 | version = '1.0' 20 | description = 'AirBnB java coding exercise' 21 | 22 | repositories { 23 | mavenCentral() 24 | } 25 | 26 | dependencies { 27 | compile 'junit:junit:4.12' 28 | compile 'org.apache.commons:commons-lang3:3.4' 29 | testCompile 'junit:junit:4.12' 30 | } 31 | 32 | sourceSets.test.java.srcDir 'src/main/java' 33 | 34 | wrapper { 35 | gradleVersion = '5.6' 36 | } 37 | 38 | tasks.register("question") { 39 | doLast { 40 | def insertUnderlineIfStartsWithDigit = { s -> 41 | if (Character.isDigit(s.charAt(0))) { 42 | s = "_" + s 43 | } 44 | s 45 | } 46 | 47 | if (!project.hasProperty('q')) { 48 | throw new InvalidUserDataException('You need to specify a question. E.g., gradle question "-Pq=Some Question"') 49 | } 50 | 51 | def question = project.q 52 | 53 | def questionPackage = insertUnderlineIfStartsWithDigit(question.replaceAll(' ', '_').toLowerCase()) 54 | 55 | def className = insertUnderlineIfStartsWithDigit(question.replaceAll(' ', '')) 56 | 57 | def questionPackageDir = new File(sourceSets.main.java.srcDirs.iterator().next(), questionPackage) 58 | if (!questionPackageDir.exists()) { 59 | println 'Create ' + questionPackageDir 60 | questionPackageDir.mkdirs() 61 | } 62 | 63 | def questionFile = new File(questionPackageDir, className + '.java') 64 | if (!questionFile.exists()) { 65 | println 'Create ' + questionFile 66 | questionFile.withWriter { out -> 67 | out.writeLine("""\ 68 | package ${questionPackage}; 69 | 70 | import java.util.*; 71 | import org.junit.*; 72 | import static org.junit.Assert.*; 73 | 74 | public class ${className} { 75 | /* 76 | */ 77 | public class Solution { 78 | 79 | } 80 | 81 | public static class UnitTest { 82 | @Test 83 | public void test1() { 84 | Solution sol = new ${className}().new Solution(); 85 | assertEquals(1, 1); 86 | } 87 | } 88 | } 89 | """) 90 | } 91 | } 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | 88 | @rem Execute Gradle 89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 90 | 91 | :end 92 | @rem End local scope for the variables with windows NT shell 93 | if "%ERRORLEVEL%"=="0" goto mainEnd 94 | 95 | :fail 96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 97 | rem the _cmd.exe /c_ return code! 98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 99 | exit /b 1 100 | 101 | :mainEnd 102 | if "%OS%"=="Windows_NT" endlocal 103 | 104 | :omega 105 | -------------------------------------------------------------------------------- /src/main/java/boggle_game/BoggleGame.java: -------------------------------------------------------------------------------- 1 | package boggle_game; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class BoggleGame { 10 | /* 11 | Boggle Game 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; 16 | 17 | private String path2Word(char[][] board, List curPath) { 18 | StringBuilder sb = new StringBuilder(); 19 | for (int[] coor : curPath) { 20 | sb.append(board[coor[0]][coor[1]]); 21 | } 22 | return sb.toString(); 23 | } 24 | 25 | private void search(List> paths, char[][] board, int x, int y, Trie trie, 26 | boolean[][] visited, List curPath) { 27 | String curWord = path2Word(board, curPath); 28 | ReturnType flag = trie.search(curWord); 29 | if (!flag.hasPrefix) { 30 | return; 31 | } 32 | if (flag.hasWord) { 33 | paths.add(new ArrayList<>(curPath)); 34 | } 35 | 36 | int m = board.length; 37 | int n = board[0].length; 38 | 39 | for (int[] dir : dirs) { 40 | int xx = x + dir[0]; 41 | int yy = y + dir[1]; 42 | 43 | if (xx < 0 || xx >= m || yy < 0 || yy >= n) { 44 | continue; 45 | } 46 | 47 | visited[xx][yy] = true; 48 | curPath.add(new int[]{xx, yy}); 49 | search(paths, board, xx, yy, trie, visited, curPath); 50 | curPath.remove(curPath.size() - 1); 51 | visited[xx][yy] = false; 52 | } 53 | } 54 | 55 | private void searchWords(List res, List curWords, List> paths, 56 | int start, boolean[][] visited, char[][] board) { 57 | if (start == paths.size()) { 58 | if (curWords.size() > res.size()) { 59 | res.clear(); 60 | res.addAll(curWords); 61 | } 62 | return; 63 | } 64 | 65 | for (int i = start; i < paths.size(); i++) { 66 | boolean canUse = true; 67 | for (int[] coor : paths.get(i)) { 68 | if (visited[coor[0]][coor[1]]) { 69 | canUse = false; 70 | break; 71 | } 72 | } 73 | 74 | if (canUse) { 75 | for (int[] coor : paths.get(i)) { 76 | visited[coor[0]][coor[1]] = true; 77 | } 78 | curWords.add(path2Word(board, paths.get(i))); 79 | searchWords(res, curWords, paths, i + 1, visited, board); 80 | curWords.remove(curWords.size() - 1); 81 | for (int[] coor : paths.get(i)) { 82 | visited[coor[0]][coor[1]] = false; 83 | } 84 | } 85 | } 86 | } 87 | 88 | public List findMostStr(char[][] board, Set dict) { 89 | List> paths = new ArrayList<>(); 90 | 91 | Trie trie = new Trie(); 92 | for (String word : dict) { 93 | trie.insert(word); 94 | } 95 | 96 | int m = board.length; 97 | int n = board[0].length; 98 | for (int i = 0; i < m; i++) { 99 | for (int j = 0; j < n; j++) { 100 | boolean[][] visited = new boolean[m][n]; 101 | visited[i][j] = true; 102 | List curPath = new ArrayList<>(); 103 | curPath.add(new int[]{i, j}); 104 | search(paths, board, i, j, trie, visited, curPath); 105 | } 106 | } 107 | 108 | List res = new ArrayList<>(); 109 | searchWords(res, new ArrayList<>(), paths, 0, new boolean[m][n], board); 110 | 111 | return res; 112 | } 113 | 114 | class ReturnType { 115 | boolean hasPrefix; 116 | boolean hasWord; 117 | 118 | ReturnType(boolean hasPrefix, boolean hasWord) { 119 | this.hasPrefix = hasPrefix; 120 | this.hasWord = hasWord; 121 | } 122 | } 123 | 124 | class TrieNode { 125 | char c; 126 | boolean isEnd; 127 | Map children; 128 | 129 | public TrieNode(char c, boolean isEnd) { 130 | this.c = c; 131 | this.isEnd = isEnd; 132 | this.children = new HashMap<>(); 133 | } 134 | } 135 | 136 | class Trie { 137 | private TrieNode root; 138 | 139 | public Trie() { 140 | this.root = new TrieNode(' ', false); 141 | } 142 | 143 | public void insert(String word) { 144 | TrieNode cur = root; 145 | for (int i = 0; i < word.length(); i++) { 146 | char c = word.charAt(i); 147 | if (!cur.children.containsKey(c)) { 148 | cur.children.put(c, new TrieNode(c, false)); 149 | } 150 | cur = cur.children.get(c); 151 | } 152 | cur.isEnd = true; 153 | } 154 | 155 | public ReturnType search(String word) { 156 | TrieNode cur = root; 157 | for (int i = 0; i < word.length(); i++) { 158 | char c = word.charAt(i); 159 | if (!cur.children.containsKey(c)) { 160 | return new ReturnType(false, false); 161 | } 162 | cur = cur.children.get(c); 163 | } 164 | return new ReturnType(true, cur.isEnd); 165 | } 166 | } 167 | } 168 | 169 | 170 | public static class UnitTest { 171 | @Test 172 | public void test1() { 173 | Solution sol = new BoggleGame().new Solution(); 174 | char[][] board = { 175 | {'o', 'a', 't', 'h'}, 176 | {'e', 't', 'a', 'e'}, 177 | {'i', 'h', 'k', 'r'}, 178 | {'i', 'f', 'l', 'v'} 179 | }; 180 | Set dict = new HashSet<>(); 181 | dict.add("oath"); 182 | dict.add("pea"); 183 | dict.add("eat"); 184 | dict.add("rain"); 185 | List res = sol.findMostStr(board, dict); 186 | assertEquals(2, res.size()); 187 | assertEquals("oath", res.get(0)); 188 | assertEquals("eat", res.get(1)); 189 | } 190 | } 191 | } 192 | 193 | -------------------------------------------------------------------------------- /src/main/java/collatz_conjecture/CollatzConjecture.java: -------------------------------------------------------------------------------- 1 | package collatz_conjecture; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class CollatzConjecture { 10 | /* 11 | Collatz Conjecture 12 | AirBnB Interview Question 13 | https://en.wikipedia.org/wiki/Collatz_conjecture 14 | */ 15 | public class Solution { 16 | private int findSteps(int num) { 17 | if (num <= 1) return 1; 18 | if (num % 2 == 0) return 1 + findSteps(num / 2); 19 | return 1 + findSteps(3 * num + 1); 20 | } 21 | 22 | public int findLongestSteps(int num) { 23 | if (num < 1) return 0; 24 | 25 | int res = 0; 26 | for (int i = 1; i <= num; i++) { 27 | int t = findSteps(i); 28 | res = Math.max(res, t); 29 | } 30 | 31 | return res; 32 | } 33 | } 34 | 35 | /* 36 | Collatz Conjecture - Memorization 37 | AirBnB Interview Question 38 | https://en.wikipedia.org/wiki/Collatz_conjecture 39 | */ 40 | public class Solution_2 { 41 | Map map = new HashMap<>(); 42 | 43 | private int findSteps(int num) { 44 | if (num <= 1) return 1; 45 | if (map.containsKey(num)) return map.get(num); 46 | if (num % 2 == 0) num = num / 2; 47 | else num = 3 * num + 1; 48 | if (map.containsKey(num)) return map.get(num) + 1; 49 | int t = findSteps(num); 50 | map.put(num, t); 51 | return t + 1; 52 | } 53 | 54 | public int findLongestSteps(int num) { 55 | if (num < 1) return 0; 56 | 57 | int res = 0; 58 | for (int i = 1; i <= num; i++) { 59 | int t = findSteps(i); 60 | map.put(i, t); 61 | res = Math.max(res, t); 62 | } 63 | 64 | return res; 65 | } 66 | } 67 | 68 | public static class UnitTest { 69 | @Test 70 | public void test1() { 71 | Solution sol = new CollatzConjecture().new Solution(); 72 | assertEquals(1, sol.findLongestSteps(1)); 73 | assertEquals(20, sol.findLongestSteps(10)); 74 | assertEquals(112, sol.findLongestSteps(37)); 75 | assertEquals(119, sol.findLongestSteps(101)); 76 | } 77 | 78 | @Test 79 | public void test2() { 80 | Solution_2 sol = new CollatzConjecture().new Solution_2(); 81 | assertEquals(1, sol.findLongestSteps(1)); 82 | assertEquals(20, sol.findLongestSteps(10)); 83 | assertEquals(112, sol.findLongestSteps(37)); 84 | assertEquals(119, sol.findLongestSteps(101)); 85 | } 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/main/java/common/Interval.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | /* 4 | Define Interval Class 5 | */ 6 | public class Interval { 7 | public int start; 8 | public int end; 9 | 10 | public Interval() { 11 | start = 0; 12 | end = 0; 13 | } 14 | 15 | public Interval(int s, int e) { 16 | start = s; 17 | end = e; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "[" + start + ", " + end + "]"; 23 | } 24 | 25 | @Override 26 | public boolean equals(Object o) { 27 | if (this == o) { 28 | return true; 29 | } 30 | if (o == null || getClass() != o.getClass()) { 31 | return false; 32 | } 33 | Interval that = (Interval) o; 34 | return start == that.start && end == that.end; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return 31 * start + end; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/common/NestedInteger.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | //import nested_list_weight_sum.NestedListWeightSum; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class NestedInteger { 9 | private List list; 10 | private Integer integer; 11 | 12 | // Constructor initializes an empty nested list. 13 | public NestedInteger() { 14 | this.list = new ArrayList<>(); 15 | } 16 | 17 | // Constructor initializes a single integer. 18 | public NestedInteger(int value) { 19 | this.integer = value; 20 | } 21 | 22 | public NestedInteger(List list) { 23 | this.list = list; 24 | } 25 | 26 | // @return true if this NestedInteger holds a single integer, rather than a nested list. 27 | public boolean isInteger() { 28 | return integer != null; 29 | } 30 | 31 | // @return the single integer that this NestedInteger holds, if it holds a single integer 32 | // Return null if this NestedInteger holds a nested list 33 | public Integer getInteger() { 34 | return integer; 35 | } 36 | 37 | // Set this NestedInteger to hold a single integer. 38 | public void setInteger(int value) { 39 | this.integer = value; 40 | } 41 | 42 | // Set this NestedInteger to hold a nested list and adds a nested integer to it. 43 | public void add(NestedInteger ni) { 44 | if (this.list != null) { 45 | this.list.add(ni); 46 | } else { 47 | this.list = new ArrayList<>(); 48 | this.list.add(ni); 49 | } 50 | } 51 | 52 | // Returns the nested list that this com.sada.linkedin.NestedInteger holds, if it holds a nested list 53 | // Returns null if this com.sada.linkedin.NestedInteger holds a single integer 54 | public List getList() { 55 | return list; 56 | } 57 | 58 | public String printNi() { 59 | if (this.isInteger()) { 60 | return String.valueOf(integer); 61 | } else { 62 | StringBuilder sb = new StringBuilder(); 63 | sb.append("["); 64 | for (int i = 0; i < list.size(); i++) { 65 | sb.append(list.get(i).printNi()); 66 | if (i != list.size() - 1) { 67 | sb.append(","); 68 | } 69 | } 70 | sb.append("]"); 71 | return sb.toString(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/common/Trie.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.util.Map; 4 | 5 | public class Trie { 6 | private TrieNode root; 7 | 8 | public Trie() { 9 | root = new TrieNode(); 10 | } 11 | 12 | // Inserts a word into the trie. 13 | public void insert(String word) { 14 | Map children = root.children; 15 | 16 | TrieNode node = root; 17 | for (char c : word.toCharArray()) { 18 | if (!node.children.containsKey(c)) { 19 | node.children.put(c, new TrieNode()); 20 | } 21 | node = node.children.get(c); 22 | } 23 | node.isLeaf = true; 24 | } 25 | 26 | // Returns if the word is in the trie. 27 | public boolean search(String word) { 28 | TrieNode t = searchNode(word); 29 | if (t != null && t.isLeaf) 30 | return true; 31 | else 32 | return false; 33 | } 34 | 35 | // Returns if there is any word in the trie 36 | // that starts with the given prefix. 37 | public boolean startsWith(String prefix) { 38 | if (searchNode(prefix) == null) 39 | return false; 40 | else 41 | return true; 42 | } 43 | 44 | public TrieNode searchNode(String str) { 45 | Map children = root.children; 46 | TrieNode t = null; 47 | for (char c : str.toCharArray()) { 48 | if (children.containsKey(c)) { 49 | t = children.get(c); 50 | children = t.children; 51 | } else { 52 | return null; 53 | } 54 | } 55 | 56 | return t; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/common/TrieNode.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class TrieNode { 7 | char c; 8 | Map children = new HashMap(); 9 | boolean isLeaf; 10 | 11 | public TrieNode() { 12 | } 13 | 14 | public TrieNode(char c) { 15 | this.c = c; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/connect_four/ConnectFour.java: -------------------------------------------------------------------------------- 1 | class ConnectFour { 2 | int row; 3 | int col; 4 | char firstPlayer; 5 | 6 | public ConnectFour(int row, int col, char firstPlayer) { 7 | this.row = row; 8 | this.col = col; 9 | this.firstPlayer = firstPlayer; 10 | } 11 | 12 | public void printBoard(char[][] board) { 13 | for (int i = 0; i < row; i++) { 14 | System.out.print("|"); 15 | for (int j = 0; j < col; j++) { 16 | System.out.print(board[i][j] + "|"); 17 | } 18 | System.out.println(); 19 | } 20 | } 21 | 22 | public boolean checkWin(char[][] board, char player) { 23 | // Check horizontal 24 | for (int i = 0; i < row; i++) { 25 | for (int j = 0; j < col - 3; j++) { 26 | if (board[i][j] == player && board[i][j + 1] == player && board[i][j + 2] == player 27 | && board[i][j + 3] == player) { 28 | return true; 29 | } 30 | } 31 | } 32 | 33 | // Check vertical 34 | for (int i = 0; i < row - 3; i++) { 35 | for (int j = 0; j < col; j++) { 36 | if (board[i][j] == player && board[i + 1][j] == player && board[i + 2][j] == player 37 | && board[i + 3][j] == player) { 38 | return true; 39 | } 40 | } 41 | } 42 | 43 | // Check diagonal 44 | for (int i = 0; i < row - 3; i++) { 45 | for (int j = 0; j < col - 3; j++) { 46 | if (board[i][j] == player && board[i + 1][j + 1] == player && board[i + 2][j + 2] == player 47 | && board[i + 3][j + 3] == player) { 48 | return true; 49 | } 50 | } 51 | } 52 | 53 | for (int i = 0; i < row - 3; i++) { 54 | for (int j = 3; j < col; j++) { 55 | if (board[i][j] == player && board[i + 1][j - 1] == player && board[i + 2][j - 2] == player 56 | && board[i + 3][j - 3] == player) { 57 | return true; 58 | } 59 | } 60 | } 61 | 62 | return false; 63 | } 64 | 65 | public void playGame(int[] moves) { 66 | char[][] board = new char[row][col]; 67 | for (int i = 0; i < row; i++) { 68 | for (int j = 0; j < col; j++) { 69 | board[i][j] = ' '; 70 | } 71 | } 72 | 73 | char currentPlayer = firstPlayer; 74 | 75 | for (int i = 0; i < moves.length; i++) { 76 | int colNum = moves[i]; 77 | if (colNum < 0 || colNum >= col || board[0][colNum] != ' ') { 78 | System.out.println("Invalid move"); 79 | continue; 80 | } 81 | 82 | for (int j = row - 1; j >= 0; j--) { 83 | if (board[j][colNum] == ' ') { 84 | board[j][colNum] = currentPlayer; 85 | break; 86 | } 87 | } 88 | 89 | if (checkWin(board, currentPlayer)) { 90 | printBoard(board); 91 | System.out.println("Player " + currentPlayer + " wins!"); 92 | break; 93 | } 94 | if (i == row * col) { 95 | printBoard(board); 96 | System.out.println("It's a draw!"); 97 | break; 98 | } 99 | 100 | currentPlayer = currentPlayer == 'X' ? 'O' : 'X'; 101 | } 102 | } 103 | 104 | public static void main(String[] args) { 105 | int[] moves = {0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5}; 106 | ConnectFour game = new ConnectFour(6, 7, 'X'); 107 | game.playGame(moves); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/csv_parser/CSVParser.java: -------------------------------------------------------------------------------- 1 | package csv_parser; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class CSVParser { 10 | /* 11 | CSV Parser 12 | AirBnB Interview Question 13 | http://creativyst.com/Doc/Articles/CSV/CSV01.htm#EmbedBRs 14 | */ 15 | public class Solution { 16 | public String parseCSV(String str) { 17 | List res = new ArrayList<>(); 18 | boolean inQuote = false; 19 | StringBuilder sb = new StringBuilder(); 20 | for (int i = 0; i < str.length(); i++) { 21 | if (inQuote) { 22 | if (str.charAt(i) == '\"') { 23 | if (i < str.length() - 1 && str.charAt(i + 1) == '\"') { 24 | sb.append("\""); 25 | i++; 26 | } else { 27 | inQuote = false; 28 | } 29 | } else { 30 | sb.append(str.charAt(i)); 31 | } 32 | } else { 33 | if (str.charAt(i) == '\"') { 34 | inQuote = true; 35 | } else if (str.charAt(i) == ',') { 36 | res.add(sb.toString()); 37 | sb.setLength(0); 38 | } else { 39 | sb.append(str.charAt(i)); 40 | } 41 | } 42 | } 43 | 44 | if (sb.length() > 0) { 45 | res.add(sb.toString()); 46 | } 47 | return String.join("|", res); 48 | } 49 | } 50 | 51 | /* 52 | CSV Parser 53 | AirBnB Interview Question 54 | http://creativyst.com/Doc/Articles/CSV/CSV01.htm#EmbedBRs 55 | */ 56 | public class Solution_2 { 57 | public String parseCSV(String str) { 58 | if (str == null || str.isEmpty()) return null; 59 | List res = new ArrayList<>(); 60 | StringBuilder curr = new StringBuilder(); 61 | boolean inQuote = false; 62 | for (int i = 0; i < str.length(); i++) { 63 | char c = str.charAt(i); 64 | if (inQuote) { 65 | if (c == '\"') { 66 | if (i < str.length() - 1 && str.charAt(i + 1) == '\"') { 67 | curr.append("\""); 68 | i++; 69 | } else { 70 | inQuote = false; 71 | } 72 | } else { 73 | curr.append(c); 74 | } 75 | } else { 76 | if (c == '\"') { 77 | inQuote = true; 78 | } else if (c == ',') { 79 | res.add(curr.toString()); 80 | curr.setLength(0); 81 | } else { 82 | curr.append(c); 83 | } 84 | } 85 | } 86 | 87 | if (curr.length() > 0) 88 | res.add(curr.toString()); 89 | 90 | return String.join("|", res); 91 | } 92 | } 93 | 94 | public static class UnitTest { 95 | @Test 96 | public void test1() { 97 | Solution sol = new CSVParser().new Solution(); 98 | String test = "John,Smith,john.smith@gmail.com,Los Angeles,1"; 99 | String expected = "John|Smith|john.smith@gmail.com|Los Angeles|1"; 100 | assertEquals(expected, sol.parseCSV(test)); 101 | 102 | test = "Jane,Roberts,janer@msn.com,\"San Francisco, CA\",0"; 103 | expected = "Jane|Roberts|janer@msn.com|San Francisco, CA|0"; 104 | assertEquals(expected, sol.parseCSV(test)); 105 | 106 | test = "\"Alexandra \"\"Alex\"\"\",Menendez,alex.menendez@gmail.com,Miami,1"; 107 | expected = "Alexandra \"Alex\"|Menendez|alex.menendez@gmail.com|Miami|1"; 108 | assertEquals(expected, sol.parseCSV(test)); 109 | 110 | test = "\"\"\"Alexandra Alex\"\"\""; 111 | expected = "\"Alexandra Alex\""; 112 | assertEquals(expected, sol.parseCSV(test)); 113 | } 114 | 115 | @Test 116 | public void test2() { 117 | Solution_2 sol = new CSVParser().new Solution_2(); 118 | String test = "John,Smith,john.smith@gmail.com,Los Angeles,1"; 119 | String expected = "John|Smith|john.smith@gmail.com|Los Angeles|1"; 120 | assertEquals(expected, sol.parseCSV(test)); 121 | 122 | test = "Jane,Roberts,janer@msn.com,\"San Francisco, CA\",0"; 123 | expected = "Jane|Roberts|janer@msn.com|San Francisco, CA|0"; 124 | assertEquals(expected, sol.parseCSV(test)); 125 | 126 | test = "\"Alexandra \"\"Alex\"\"\",Menendez,alex.menendez@gmail.com,Miami,1"; 127 | expected = "Alexandra \"Alex\"|Menendez|alex.menendez@gmail.com|Miami|1"; 128 | assertEquals(expected, sol.parseCSV(test)); 129 | 130 | test = "\"\"\"Alexandra Alex\"\"\""; 131 | expected = "\"Alexandra Alex\""; 132 | assertEquals(expected, sol.parseCSV(test)); 133 | } 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/main/java/display_page/DisplayPage.java: -------------------------------------------------------------------------------- 1 | package display_page; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class DisplayPage { 10 | /* 11 | Display Page - LinkedList + HashSet 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public List displayPages(List input, int pageSize) { 16 | List res = new ArrayList<>(); 17 | if (input == null || input.size() == 0) { 18 | return res; 19 | } 20 | 21 | List visited = new ArrayList<>(); 22 | Iterator iter = input.iterator(); 23 | boolean reachEnd = false; 24 | while (iter.hasNext()) { 25 | String curr = iter.next(); 26 | String hostId = curr.split(",")[0]; 27 | if (!visited.contains(hostId) || reachEnd) { 28 | res.add(curr); 29 | visited.add(hostId); 30 | iter.remove(); 31 | } 32 | 33 | if (visited.size() == pageSize) { 34 | visited.clear(); 35 | reachEnd = false; 36 | if (!input.isEmpty()) { 37 | res.add(" "); 38 | } 39 | iter = input.iterator(); 40 | } 41 | 42 | if (!iter.hasNext()) { 43 | iter = input.iterator(); 44 | reachEnd = true; 45 | } 46 | } 47 | 48 | return res; 49 | } 50 | } 51 | 52 | /* 53 | Display Page - Fill each page 54 | AirBnB Interview Question 55 | */ 56 | public class Solution_2 { 57 | public List displayPages(List input, int pageSize) { 58 | List res = new ArrayList<>(); 59 | Iterator iter = input.iterator(); 60 | Set set = new HashSet<>(); 61 | boolean reachEnd = false; 62 | int counter = 0; 63 | while (iter.hasNext()) { 64 | String cur = iter.next(); 65 | String id = (cur.split(","))[0]; 66 | if (!set.contains(id) || reachEnd) { 67 | res.add(cur); 68 | set.add(id); 69 | iter.remove(); 70 | counter++; 71 | } 72 | 73 | if (counter == pageSize) { 74 | if (!input.isEmpty()) 75 | res.add(" "); 76 | set.clear(); 77 | counter = 0; 78 | reachEnd = false; 79 | iter = input.iterator(); 80 | } 81 | 82 | if (!iter.hasNext()) { 83 | reachEnd = true; 84 | iter = input.iterator(); 85 | } 86 | } 87 | 88 | return res; 89 | } 90 | } 91 | 92 | public static class UnitTest { 93 | @Test 94 | public void test1() { 95 | Solution sol = new DisplayPage().new Solution(); 96 | String[] strs = new String[]{ 97 | "1,28,300.1,SanFrancisco", 98 | "4,5,209.1,SanFrancisco", 99 | "20,7,208.1,SanFrancisco", 100 | "23,8,207.1,SanFrancisco", 101 | "16,10,206.1,Oakland", 102 | "1,16,205.1,SanFrancisco", 103 | "6,29,204.1,SanFrancisco", 104 | "7,20,203.1,SanFrancisco", 105 | "8,21,202.1,SanFrancisco", 106 | "2,18,201.1,SanFrancisco", 107 | "2,30,200.1,SanFrancisco", 108 | "15,27,109.1,Oakland", 109 | "10,13,108.1,Oakland", 110 | "11,26,107.1,Oakland", 111 | "12,9,106.1,Oakland", 112 | "13,1,105.1,Oakland", 113 | "22,17,104.1,Oakland", 114 | "1,2,103.1,Oakland", 115 | "28,24,102.1,Oakland", 116 | "18,14,11.1,SanJose", 117 | "6,25,10.1,Oakland", 118 | "19,15,9.1,SanJose", 119 | "3,19,8.1,SanJose", 120 | "3,11,7.1,Oakland", 121 | "27,12,6.1,Oakland", 122 | "1,3,5.1,Oakland", 123 | "25,4,4.1,SanJose", 124 | "5,6,3.1,SanJose", 125 | "29,22,2.1,SanJose", 126 | "30,23,1.1,SanJose" 127 | }; 128 | List input = new ArrayList<>(Arrays.asList(strs)); 129 | List result = sol.displayPages(input, 12); 130 | assertEquals(32, result.size()); 131 | assertEquals("1,28,300.1,SanFrancisco", result.get(0)); 132 | assertEquals("11,26,107.1,Oakland", result.get(11)); 133 | assertEquals(" ", result.get(12)); 134 | assertEquals("1,16,205.1,SanFrancisco", result.get(13)); 135 | assertEquals("2,30,200.1,SanFrancisco", result.get(14)); 136 | assertEquals("25,4,4.1,SanJose", result.get(24)); 137 | assertEquals(" ", result.get(25)); 138 | assertEquals("1,2,103.1,Oakland", result.get(26)); 139 | assertEquals("3,11,7.1,Oakland", result.get(27)); 140 | assertEquals("30,23,1.1,SanJose", result.get(30)); 141 | assertEquals("1,3,5.1,Oakland", result.get(31)); 142 | } 143 | 144 | @Test 145 | public void test2() { 146 | Solution_2 sol = new DisplayPage().new Solution_2(); 147 | String[] strs = new String[]{ 148 | "1,28,310.6,SF", 149 | "4,5,204.1,SF", 150 | "20,7,203.2,Oakland", 151 | "6,8,202.2,SF", 152 | "6,10,199.1,SF", 153 | "1,16,190.4,SF", 154 | "6,29,185.2,SF", 155 | "7,20,180.1,SF", 156 | "6,21,162.1,SF", 157 | "2,18,161.2,SF", 158 | "2,30,149.1,SF", 159 | "3,76,146.2,SF", 160 | "2,14,141.1,San Jose" 161 | 162 | }; 163 | List input = new ArrayList<>(Arrays.asList(strs)); 164 | List result = sol.displayPages(input, 5); 165 | assertEquals(15, result.size()); 166 | assertEquals("1,28,310.6,SF", result.get(0)); 167 | assertEquals("7,20,180.1,SF", result.get(4)); 168 | assertEquals(" ", result.get(5)); 169 | assertEquals("6,10,199.1,SF", result.get(6)); 170 | assertEquals("6,29,185.2,SF", result.get(10)); 171 | assertEquals(" ", result.get(11)); 172 | assertEquals("6,21,162.1,SF", result.get(12)); 173 | assertEquals("2,14,141.1,San Jose", result.get(14)); 174 | } 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/main/java/file_system/FileSystem.java: -------------------------------------------------------------------------------- 1 | package file_system; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class FileSystem { 10 | /* 11 | File System 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | Map pathMap; 16 | Map callbackMap; 17 | 18 | public Solution() { 19 | this.pathMap = new HashMap<>(); 20 | this.callbackMap = new HashMap<>(); 21 | this.pathMap.put("", 0); 22 | } 23 | 24 | public boolean create(String path, int value) { 25 | if (pathMap.containsKey(path)) { 26 | return false; 27 | } 28 | 29 | int lastSlashIndex = path.lastIndexOf("/"); 30 | if (!pathMap.containsKey(path.substring(0, lastSlashIndex))) { 31 | return false; 32 | } 33 | 34 | pathMap.put(path, value); 35 | return true; 36 | } 37 | 38 | public boolean set(String path, int value) { 39 | if (!pathMap.containsKey(path)) { 40 | return false; 41 | } 42 | 43 | pathMap.put(path, value); 44 | 45 | // Trigger callbacks 46 | String curPath = path; 47 | // while (curPath.length() > 0) { 48 | // if (callbackMap.containsKey(curPath)) { 49 | // callbackMap.get(curPath).run(); 50 | // } 51 | // int lastSlashIndex = path.lastIndexOf("/"); 52 | // curPath = curPath.substring(0, lastSlashIndex); 53 | // } 54 | 55 | return true; 56 | } 57 | 58 | public Integer get(String path) { 59 | return pathMap.get(path); 60 | } 61 | 62 | public boolean watch(String path, Runnable callback) { 63 | if (!pathMap.containsKey(path)) { 64 | return false; 65 | } 66 | 67 | callbackMap.put(path, callback); 68 | return true; 69 | } 70 | } 71 | 72 | public static class UnitTest { 73 | @Test 74 | public void test1() { 75 | Solution sol = new FileSystem().new Solution(); 76 | assertTrue(sol.create("/a",1)); 77 | assertEquals(1, (int)sol.get("/a")); 78 | assertTrue(sol.create("/a/b",2)); 79 | assertEquals(2, (int)sol.get("/a/b")); 80 | assertTrue(sol.set("/a/b",3)); 81 | assertEquals(3, (int)sol.get("/a/b")); 82 | assertFalse(sol.create("/c/d",4)); 83 | assertFalse(sol.set("/c/d",4)); 84 | 85 | sol = new FileSystem().new Solution(); 86 | assertTrue(sol.create("/NA",1)); 87 | assertTrue(sol.create("/EU",2)); 88 | assertEquals(1, (int)sol.get("/NA")); 89 | assertTrue(sol.create("/NA/CA",101)); 90 | assertEquals(101, (int)sol.get("/NA/CA")); 91 | assertTrue(sol.set("/NA/CA",102)); 92 | assertEquals(102, (int)sol.get("/NA/CA")); 93 | assertTrue(sol.create("/NA/US",101)); 94 | assertEquals(101, (int)sol.get("/NA/US")); 95 | assertFalse(sol.create("/NA/CA",101)); 96 | assertFalse(sol.create("/SA/MX",103)); 97 | assertFalse(sol.set("SA/MX",103)); 98 | } 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/main/java/find_case_combinations_of_a_string/FindCaseCombinationsofaString.java: -------------------------------------------------------------------------------- 1 | package find_case_combinations_of_a_string; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class FindCaseCombinationsofaString { 10 | /* 11 | Find Case Combinations of a String 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private boolean isBitSet(int n, int offset) { 16 | return (n >> offset & 1) != 0; 17 | } 18 | 19 | public List strComb(String text) { 20 | List res = new ArrayList<>(); 21 | if (text == null || text.length() == 0) { 22 | return res; 23 | } 24 | char[] chars = text.toCharArray(); 25 | for (int i = 0, n = (int) Math.pow(2, chars.length); i < n; i++) { 26 | char[] curr = new char[chars.length]; 27 | for (int j = 0; j < chars.length; j++) { 28 | curr[j] = (isBitSet(i, j)) ? Character.toUpperCase(chars[j]) : Character.toLowerCase(chars[j]); 29 | } 30 | res.add(new String(curr)); 31 | } 32 | return res; 33 | } 34 | 35 | } 36 | 37 | public static class UnitTest { 38 | @Test 39 | public void test1() { 40 | Solution sol = new FindCaseCombinationsofaString().new Solution(); 41 | List res = sol.strComb("AirBnB"); 42 | assertEquals(64, res.size()); 43 | assertEquals("airbnb", res.get(0)); 44 | assertEquals("Airbnb", res.get(1)); 45 | assertEquals("aIRBNB", res.get(62)); 46 | assertEquals("AIRBNB", res.get(63)); 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/find_median_in_large_file_of_integers/FindMedianinLargeIntegerFileofIntegers.java: -------------------------------------------------------------------------------- 1 | package find_median_in_large_file_of_integers; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class FindMedianinLargeIntegerFileofIntegers { 8 | /* 9 | Find Median in Large Integer File of Integers 10 | AirBnB Interview Question 11 | */ 12 | public class Solution { 13 | private long search(int[] nums, int k, long left, long right) { 14 | if (left >= right) { 15 | return left; 16 | } 17 | 18 | long res = left; 19 | long guess = left + (right - left) / 2; 20 | int count = 0; 21 | for (int num : nums) { 22 | if (num <= guess) { 23 | count++; 24 | res = Math.max(res, num); 25 | } 26 | } 27 | 28 | if (count == k) { 29 | return res; 30 | } else if (count < k) { 31 | return search(nums, k, Math.max(res + 1, guess), right); 32 | } else { 33 | return search(nums, k, left, res); 34 | } 35 | } 36 | 37 | public double findMedian(int[] nums) { 38 | int len = 0; 39 | for (int num : nums) { 40 | len++; 41 | } 42 | 43 | if (len % 2 == 1) { 44 | return (double) search(nums, len / 2 + 1, Integer.MIN_VALUE, Integer.MAX_VALUE); 45 | } else { 46 | return (double) (search(nums, len / 2, Integer.MIN_VALUE, Integer.MAX_VALUE) + 47 | search(nums, len / 2 + 1, Integer.MIN_VALUE, Integer.MAX_VALUE)) / 2; 48 | } 49 | } 50 | } 51 | 52 | public static class UnitTest { 53 | @Test 54 | public void test1() { 55 | Solution sol = new FindMedianinLargeIntegerFileofIntegers().new Solution(); 56 | assertEquals(3.0, sol.findMedian(new int[]{3, -2, 7}), 1E-03); 57 | assertEquals(5.0, sol.findMedian(new int[]{-100, 99, 3, 0, 5, 7, 11, 66, -33}), 1E-03); 58 | assertEquals(4.5, sol.findMedian(new int[]{4, -100, 99, 3, 0, 5, 7, 11, 66, -33}), 1E-03); 59 | } 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/finding_ocean/FindingOcean.java: -------------------------------------------------------------------------------- 1 | package finding_ocean; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class FindingOcean { 10 | /* 11 | Finding Ocean 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public void floodFill(char[][] board, int i, int j, char oldColor, char newColor) { 16 | if (board[i][j] != oldColor || board[i][j] == newColor) { 17 | return; 18 | } 19 | 20 | Queue queue = new LinkedList<>(); 21 | queue.add(i * board[0].length + j); 22 | board[i][j] = newColor; 23 | 24 | while (!queue.isEmpty()) { 25 | int pos = queue.poll(); 26 | int m = pos / board[0].length; 27 | int n = pos % board[0].length; 28 | 29 | if (m + 1 < board.length && board[m + 1][n] == oldColor) { 30 | queue.add((m + 1) * board[0].length + n); 31 | board[m + 1][n] = newColor; 32 | } 33 | if (m - 1 >= 0 && board[m - 1][n] == oldColor) { 34 | queue.add((m - 1) * board[0].length + n); 35 | board[m - 1][n] = newColor; 36 | } 37 | if (n + 1 < board[0].length && board[m][n + 1] == oldColor) { 38 | queue.add(m * board[0].length + n + 1); 39 | board[m][n + 1] = newColor; 40 | } 41 | if (n - 1 >= 0 && board[m][n - 1] == oldColor) { 42 | queue.add(m * board[0].length + n - 1); 43 | board[m][n - 1] = newColor; 44 | } 45 | } 46 | } 47 | } 48 | 49 | public static class UnitTest { 50 | @Test 51 | public void test1() { 52 | Solution sol = new FindingOcean().new Solution(); 53 | List testData = new ArrayList() {{ 54 | add("WWWLLLW"); 55 | add("WWLLLWW"); 56 | add("WLLLLWW"); 57 | }}; 58 | char[][] map = new char[testData.size()][testData.get(0).length()]; 59 | for (int i = 0; i < testData.size(); i++) 60 | for (int j = 0; j < testData.get(i).length(); j++) 61 | map[i][j] = testData.get(i).charAt(j); 62 | 63 | sol.floodFill(map, 0, 0, 'W', 'O'); 64 | assertEquals('O', map[0][0]); 65 | 66 | 67 | testData = new ArrayList() {{ 68 | add("LLLLLLLLLLLLLLLLLLLL"); 69 | add("LLLLLLLLLLLLLLLLLLLL"); 70 | add("LLLLLLLLLLLLLLWLLLLL"); 71 | add("LLWWLLLLLLLLLLLLLLLL"); 72 | add("LLWWLLLLLLLLLLLLLLLL"); 73 | add("LLLLLLLLLLLLLLLLLLLL"); 74 | add("LLLLLLLWWLLLLLLLLLLL"); 75 | add("LLLLLLLLWWLLLLLLLLLL"); 76 | add("LLLLLLLLLWWWLLLLLLLL"); 77 | add("LLLLLLLLLLWWWWWWLLLL"); 78 | add("LLLLLLLLLLWWWWWWLLLL"); 79 | add("LLLLLLLLLLWWWWWWLLLL"); 80 | add("LLLLWWLLLLWWWWWWLLLL"); 81 | add("LLLLWWWLLLWWWWWWWWWW"); 82 | add("LLLLLWWWWWWWWWWWLLLL"); 83 | add("LLLLLLLLLLLLLLWWWWLL"); 84 | add("LLLLLLLLLLLLLLWLLLLL"); 85 | add("LLLLWLLLLLLLLLLLLWLL"); 86 | add("LLLLLLLLLLLLLLLLLLWL"); 87 | }}; 88 | 89 | map = new char[testData.size()][testData.get(0).length()]; 90 | for (int i = 0; i < testData.size(); i++) 91 | for (int j = 0; j < testData.get(i).length(); j++) 92 | map[i][j] = testData.get(i).charAt(j); 93 | sol.floodFill(map, 9, 12, 'W', 'O'); 94 | assertEquals('O', map[9][11]); 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /src/main/java/guess_number/GuessNumber.java: -------------------------------------------------------------------------------- 1 | package guess_number; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class GuessNumber { 10 | /* 11 | Guess Number 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | String target; 16 | 17 | public Solution(String target) { 18 | this.target = target; 19 | } 20 | 21 | private int guessServer(String guess) { 22 | int res = 0; 23 | Map targetMap = new HashMap<>(); 24 | for (char c : target.toCharArray()) targetMap.put(c, targetMap.getOrDefault(c, 0) + 1); 25 | Map guessMap = new HashMap<>(); 26 | for (char c : guess.toCharArray()) guessMap.put(c, guessMap.getOrDefault(c, 0) + 1); 27 | for (char k : guessMap.keySet()) { 28 | if (targetMap.containsKey(k)) 29 | res += Math.min(guessMap.get(k), targetMap.get(k)); 30 | } 31 | return res; 32 | } 33 | 34 | private String genNumber(List guessed, int c) { 35 | StringBuilder sb = new StringBuilder(); 36 | for (int i = 0; i < guessed.size(); i++) 37 | sb.append(guessed.get(i)); 38 | for (int i = guessed.size(); i < 4; i++) 39 | sb.append(c); 40 | return sb.toString(); 41 | } 42 | 43 | private String genNumber(List guessed) { 44 | if (guessed == null || guessed.size() == 0) return ""; 45 | StringBuilder sb = new StringBuilder(); 46 | for (int i = 0; i < guessed.size(); i++) 47 | sb.append(guessed.get(i)); 48 | return sb.toString(); 49 | } 50 | 51 | public String guess() { 52 | List res = new ArrayList<>(); 53 | List cands = new ArrayList() {{ 54 | add(1); 55 | add(2); 56 | add(3); 57 | add(4); 58 | add(5); 59 | // insert(6); 60 | }}; 61 | // System.out.println("\nstart to guess " + target + " ..."); 62 | // System.out.println("res: " + res); 63 | // System.out.println("candList: " + candList); 64 | int counter = 0; 65 | Iterator iter = cands.iterator(); 66 | while (iter.hasNext() && res.size() < 4) { 67 | int cand = iter.next(); 68 | counter++; 69 | int guessedCount = res.size(); 70 | String guessCand = genNumber(res, cand); 71 | int guessRes = guessServer(guessCand); 72 | // System.out.println("cand: " + cand); 73 | // System.out.println("guessRes: " + guessRes); 74 | if (guessRes == guessedCount) { 75 | iter.remove(); 76 | } else if (guessRes > guessedCount) { 77 | for (int i = guessedCount; i < guessRes; i++) { 78 | res.add(cand); 79 | } 80 | iter.remove(); 81 | } else { 82 | // something wrong here 83 | return genNumber(res); 84 | } 85 | } 86 | if (res.size() < 4) { 87 | for (int i = res.size(); i < 4; i++) 88 | res.add(6); 89 | } 90 | 91 | // System.out.println("guessed " + counter + " times"); 92 | return genNumber(res); 93 | } 94 | } 95 | 96 | public static class UnitTest { 97 | @Test 98 | public void test() { 99 | String guess = "2345"; 100 | Solution sol = new GuessNumber().new Solution(guess); 101 | assertEquals(guess, sol.guess()); 102 | 103 | guess = "3456"; 104 | sol = new GuessNumber().new Solution(guess); 105 | assertEquals(guess, sol.guess()); 106 | 107 | guess = "4536"; 108 | sol = new GuessNumber().new Solution(guess); 109 | char[] res = guess.toCharArray(); 110 | Arrays.sort(res); 111 | assertEquals(new String(res), sol.guess()); 112 | 113 | guess = "1111"; 114 | sol = new GuessNumber().new Solution(guess); 115 | assertEquals(guess, sol.guess()); 116 | 117 | guess = "6666"; 118 | sol = new GuessNumber().new Solution(guess); 119 | assertEquals(guess, sol.guess()); 120 | 121 | guess = "2266"; 122 | sol = new GuessNumber().new Solution(guess); 123 | assertEquals(guess, sol.guess()); 124 | 125 | guess = "5566"; 126 | sol = new GuessNumber().new Solution(guess); 127 | assertEquals(guess, sol.guess()); 128 | } 129 | } 130 | } 131 | 132 | -------------------------------------------------------------------------------- /src/main/java/hilbert_curve/HilbertCurve.java: -------------------------------------------------------------------------------- 1 | package hilbert_curve; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class HilbertCurve { 10 | /* 11 | Hilbert Curve 12 | https://en.wikipedia.org/wiki/Hilbert_curve 13 | AirBnB Interview Question 14 | */ 15 | public class Solution { 16 | public int hilbertCurve(int x, int y, int iter) { 17 | if (iter == 0) return 1; 18 | int len = 1 << (iter - 1); 19 | int num = 1 << (2 * (iter - 1)); 20 | 21 | if (x >= len && y >= len) { 22 | // 3 Shape is identical with previous iteration 23 | return 2 * num + hilbertCurve(x - len, y - len, iter - 1); 24 | } else if (x < len && y >= len) { 25 | // 2 Shape is identical with previous iteration 26 | return num + hilbertCurve(x, y - len, iter - 1); 27 | } else if (x < len && y < len) { 28 | // 1 Clock-wise rotate 90 29 | return hilbertCurve(y, x, iter - 1); 30 | } else { 31 | // 4 Anti-Clockwise rotate 90 32 | return 3 * num + hilbertCurve(len - y - 1, 2 * len - x - 1, iter - 1); 33 | } 34 | } 35 | } 36 | 37 | public static class UnitTest { 38 | @Test 39 | public void test1() { 40 | Solution sol = new HilbertCurve().new Solution(); 41 | assertEquals(3, sol.hilbertCurve(1, 1, 2)); 42 | assertEquals(2, sol.hilbertCurve(0, 1, 1)); 43 | assertEquals(9, sol.hilbertCurve(2, 2, 2)); 44 | } 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/implement_queue_with_fixed_size_of_arrays/ImplementQueuewithFixedSizeofArrays.java: -------------------------------------------------------------------------------- 1 | package implement_queue_with_fixed_size_of_arrays; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class ImplementQueuewithFixedSizeofArrays { 10 | /* 11 | Implement Queue with Fixed Size of Arrays 12 | AirBnB Interview Question 13 | */ 14 | public class QueueWithFixedArray { 15 | private int fixedSize; 16 | 17 | private int count; 18 | private int head; 19 | private int tail; 20 | private List headList; 21 | private List tailList; 22 | 23 | public QueueWithFixedArray(int fixedSize) { 24 | this.fixedSize = fixedSize; 25 | this.count = 0; 26 | this.head = 0; 27 | this.tail = 0; 28 | this.headList = new ArrayList<>(); 29 | this.tailList = this.headList; 30 | } 31 | 32 | public void offer(int num) { 33 | if (tail == fixedSize - 1) { 34 | List newList = new ArrayList<>(); 35 | newList.add(num); 36 | tailList.add(newList); 37 | tailList = (List) tailList.get(tail); 38 | tail = 0; 39 | } else { 40 | tailList.add(num); 41 | } 42 | count++; 43 | tail++; 44 | } 45 | 46 | public Integer poll() { 47 | if (count == 0) { 48 | return null; 49 | } 50 | 51 | int num = (int) headList.get(head); 52 | head++; 53 | count--; 54 | 55 | if (head == fixedSize - 1) { 56 | List newList = (List) headList.get(head); 57 | headList.clear(); 58 | headList = newList; 59 | head = 0; 60 | } 61 | 62 | return num; 63 | } 64 | 65 | public int size() { 66 | return count; 67 | } 68 | } 69 | 70 | public static class UnitTest { 71 | @Test 72 | public void test1() { 73 | QueueWithFixedArray queue = new ImplementQueuewithFixedSizeofArrays().new QueueWithFixedArray(5); 74 | queue.offer(1); 75 | queue.offer(2); 76 | int res = queue.poll(); 77 | assertEquals(1, res); 78 | queue.offer(3); 79 | queue.offer(4); 80 | queue.offer(5); 81 | queue.offer(6); 82 | queue.offer(7); 83 | queue.offer(8); 84 | queue.offer(9); 85 | res = queue.poll(); 86 | assertEquals(2, res); 87 | res = queue.poll(); 88 | assertEquals(3, res); 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/main/java/ip_range_to_cidr/IPRangetoCIDR.java: -------------------------------------------------------------------------------- 1 | package ip_range_to_cidr; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class IPRangetoCIDR { 10 | /* 11 | IP range to CIDR 12 | https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing 13 | http://www.ipaddressguide.com/cidr 14 | https://stackoverflow.com/questions/33443914/how-to-convert-ip-address-range-to-cidr-in-java 15 | AirBnB Interview Question 16 | */ 17 | public class Solution { 18 | private long ipToLong(String strIP) { 19 | long[] ip = new long[4]; 20 | String[] ipSec = strIP.split("\\."); 21 | for (int k = 0; k < 4; k++) { 22 | ip[k] = Long.valueOf(ipSec[k]); 23 | } 24 | 25 | return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; 26 | } 27 | 28 | private String longToIP(long longIP) { 29 | StringBuffer sb = new StringBuffer(""); 30 | sb.append(String.valueOf(longIP >>> 24)); 31 | sb.append("."); 32 | sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16)); 33 | sb.append("."); 34 | sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8)); 35 | sb.append("."); 36 | sb.append(String.valueOf(longIP & 0x000000FF)); 37 | 38 | return sb.toString(); 39 | } 40 | 41 | public List ipRange2Cidr(String startIp, int range) { 42 | // check parameters 43 | String a = ""; 44 | long start = ipToLong(startIp); 45 | long end = start + range - 1; 46 | List res = new ArrayList<>(); 47 | while (start <= end) { 48 | // identify the location of first 1's from lower bit to higher bit of start IP 49 | // e.g. 00000001.00000001.00000001.01101100, return 4 (100) 50 | long locOfFirstOne = start & (-start); 51 | int curMask = 32 - (int) (Math.log(locOfFirstOne) / Math.log(2)); 52 | 53 | // calculate how many IP addresses between the start and end 54 | // e.g. between 1.1.1.111 and 1.1.1.120, there are 10 IP address 55 | // 3 bits to represent 8 IPs, from 1.1.1.112 to 1.1.1.119 (119 - 112 + 1 = 8) 56 | double currRange = Math.log(end - start + 1) / Math.log(2); 57 | int currRangeMask = 32 - (int) Math.floor(currRange); 58 | 59 | // why max? 60 | // if the currRangeMask is larger than curMask 61 | // which means the numbers of IPs from start to end is smaller than mask range 62 | // so we can't use as many as bits we want to mask the start IP to avoid exceed the end IP 63 | // Otherwise, if currRangeMask is smaller than curMask, which means number of IPs is larger than mask range 64 | // in this case we can use curMask to mask as many as IPs from start we want. 65 | curMask = Math.max(currRangeMask, curMask); 66 | 67 | // Add to results 68 | String ip = longToIP(start); 69 | res.add(ip + "/" + curMask); 70 | // We have already included 2^(32 - curMask) numbers of IP into result 71 | // So the next roundUp start must insert that number 72 | start += Math.pow(2, (32 - curMask)); 73 | } 74 | return res; 75 | } 76 | } 77 | 78 | public static class UnitTest { 79 | @Test 80 | public void test1() { 81 | Solution sol = new IPRangetoCIDR().new Solution(); 82 | List res = sol.ipRange2Cidr("255.0.0.7", 10); 83 | assertEquals(3, res.size()); 84 | assertEquals("255.0.0.7/32", res.get(0)); 85 | assertEquals("255.0.0.8/29", res.get(1)); 86 | assertEquals("255.0.0.16/32", res.get(2)); 87 | 88 | res = sol.ipRange2Cidr("1.1.1.0", 4); 89 | assertEquals(1, res.size()); 90 | assertEquals("1.1.1.0/30", res.get(0)); 91 | 92 | res = sol.ipRange2Cidr("1.1.1.1", 4); 93 | assertEquals(3, res.size()); 94 | assertEquals("1.1.1.1/32", res.get(0)); 95 | assertEquals("1.1.1.2/31", res.get(1)); 96 | assertEquals("1.1.1.4/32", res.get(2)); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/main/java/k_edit_distance/KEditDistance.java: -------------------------------------------------------------------------------- 1 | package k_edit_distance; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class KEditDistance { 10 | /* 11 | K Edit Distance 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private void search(String curr, String target, int k, TrieNode root, 16 | int[] prevDist, List result) { 17 | if (root.isLeaf) { 18 | if (prevDist[target.length()] <= k) { 19 | result.add(curr); 20 | } else { 21 | return; 22 | } 23 | } 24 | 25 | for (int i = 0; i < 26; i++) { 26 | if (root.children[i] == null) { 27 | continue; 28 | } 29 | 30 | int[] currDist = new int[target.length() + 1]; 31 | currDist[0] = curr.length() + 1; 32 | for (int j = 1; j < prevDist.length; j++) { 33 | if (target.charAt(j - 1) == (char) (i + 'a')) { 34 | currDist[j] = prevDist[j - 1]; 35 | } else { 36 | currDist[j] = Math.min(Math.min(prevDist[j - 1], prevDist[j]), currDist[j - 1]) + 1; 37 | } 38 | } 39 | 40 | search(curr + (char) (i + 'a'), target, k, root.children[i], currDist, result); 41 | } 42 | } 43 | 44 | public List getKEditDistance(String[] words, String target, int k) { 45 | List res = new ArrayList<>(); 46 | if (words == null || words.length == 0 || target == null || 47 | target.length() == 0 || k < 0) { 48 | return res; 49 | } 50 | 51 | Trie trie = new Trie(); 52 | for (String word : words) { 53 | trie.insert(word); 54 | } 55 | 56 | TrieNode root = trie.root; 57 | // The edit distance from curr to target 58 | int[] prev = new int[target.length() + 1]; 59 | for (int i = 0; i < prev.length; i++) { 60 | prev[i] = i; 61 | } 62 | 63 | search("", target, k, root, prev, res); 64 | 65 | return res; 66 | } 67 | 68 | class TrieNode { 69 | TrieNode[] children; 70 | boolean isLeaf; 71 | 72 | public TrieNode() { 73 | children = new TrieNode[26]; 74 | } 75 | } 76 | 77 | class Trie { 78 | TrieNode root; 79 | 80 | public Trie() { 81 | root = new TrieNode(); 82 | } 83 | 84 | // Add a word into trie 85 | public void insert(String s) { 86 | if (s == null || s.length() == 0) { 87 | return; 88 | } 89 | 90 | TrieNode p = root; 91 | for (int i = 0; i < s.length(); i++) { 92 | char c = s.charAt(i); 93 | if (p.children[c - 'a'] == null) { 94 | p.children[c - 'a'] = new TrieNode(); 95 | } 96 | 97 | if (i == s.length() - 1) { 98 | p.children[c - 'a'].isLeaf = true; 99 | } 100 | 101 | p = p.children[c - 'a']; 102 | } 103 | } 104 | } 105 | } 106 | 107 | public static class UnitTest { 108 | @Test 109 | public void test1() { 110 | Solution sol = new KEditDistance().new Solution(); 111 | String[] input = new String[]{"abcd", "abc", "abd", "ad", "c", "cc"}; 112 | String target = "abcd"; 113 | int k = 2; 114 | List res = sol.getKEditDistance(input, target, k); 115 | assertEquals(4, res.size()); 116 | } 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/main/java/list_of_list_iterator/ListofListIterator.java: -------------------------------------------------------------------------------- 1 | package list_of_list_iterator; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class ListofListIterator { 10 | /* 11 | List of List Iterator 12 | AirBnB Interview Question 13 | */ 14 | public class Solution implements Iterator { 15 | private int row, col; 16 | private List> vec2d; 17 | 18 | public Solution(List> vec) { 19 | row = 0; 20 | col = 0; 21 | vec2d = vec; 22 | } 23 | 24 | @Override 25 | public Integer next() { 26 | int val = vec2d.get(row).get(col); 27 | col++; 28 | return val; 29 | } 30 | 31 | @Override 32 | public boolean hasNext() { 33 | if (vec2d == null || vec2d.isEmpty()) 34 | return false; 35 | while (row < vec2d.size()) { 36 | if (col < vec2d.get(row).size()) { 37 | return true; 38 | } else { 39 | row++; 40 | col = 0; 41 | } 42 | } 43 | return false; 44 | } 45 | 46 | @Override 47 | public void remove() { 48 | List listToBeRemoved; 49 | int rowToBeRemoved = row; 50 | int colToBeRemoved = col; 51 | if (col == 0) { 52 | rowToBeRemoved--; 53 | colToBeRemoved = vec2d.get(rowToBeRemoved).size() - 1; 54 | listToBeRemoved = vec2d.get(rowToBeRemoved); 55 | } else { 56 | colToBeRemoved--; 57 | listToBeRemoved = vec2d.get(rowToBeRemoved); 58 | } 59 | listToBeRemoved.remove(colToBeRemoved); 60 | if (listToBeRemoved.isEmpty()) { 61 | vec2d.remove(listToBeRemoved); 62 | row--; 63 | } 64 | if (col > 0) 65 | col--; 66 | } 67 | } 68 | 69 | 70 | /* 71 | List of List Iterator 72 | AirBnB Interview Question 73 | */ 74 | public class Solution_2 implements Iterator { 75 | private Iterator> rowIter; 76 | private Iterator colIter; 77 | 78 | public Solution_2(List> vec2d) { 79 | rowIter = vec2d.iterator(); 80 | colIter = Collections.emptyIterator(); 81 | } 82 | 83 | @Override 84 | public Integer next() { 85 | return colIter.next(); 86 | } 87 | 88 | @Override 89 | public boolean hasNext() { 90 | while ((colIter == null || !colIter.hasNext()) && rowIter.hasNext()) 91 | colIter = rowIter.next().iterator(); 92 | return colIter != null && colIter.hasNext(); 93 | } 94 | 95 | @Override 96 | public void remove() { 97 | while (colIter == null && rowIter.hasNext()) 98 | colIter = rowIter.next().iterator(); 99 | if (colIter != null) 100 | colIter.remove(); 101 | } 102 | } 103 | 104 | 105 | public static class UnitTest { 106 | @Test 107 | public void test1() { 108 | List> test = new ArrayList<>(); 109 | test.add(new ArrayList() {{ 110 | add(1); 111 | add(2); 112 | }}); 113 | test.add(new ArrayList() {{ 114 | add(3); 115 | }}); 116 | test.add(new ArrayList() {{ 117 | add(4); 118 | add(5); 119 | add(6); 120 | }}); 121 | Solution sol = new ListofListIterator().new Solution(test); 122 | assertTrue(sol.hasNext()); 123 | assertEquals(1, (int) sol.next()); 124 | sol.remove(); 125 | List res = new ArrayList<>(); 126 | while (sol.hasNext()) { 127 | res.add(sol.next()); 128 | } 129 | assertEquals(5, res.size()); 130 | assertEquals(2, (int) res.get(0)); 131 | assertEquals(4, (int) res.get(2)); 132 | assertEquals(6, (int) res.get(4)); 133 | 134 | test = new ArrayList<>(); 135 | test.add(new ArrayList() {{ 136 | add(1); 137 | add(2); 138 | }}); 139 | test.add(new ArrayList() {{ 140 | add(3); 141 | }}); 142 | sol = new ListofListIterator().new Solution(test); 143 | assertTrue(sol.hasNext()); 144 | assertEquals(1, (int) sol.next()); 145 | assertTrue(sol.hasNext()); 146 | assertEquals(2, (int) sol.next()); 147 | sol.remove(); 148 | assertTrue(sol.hasNext()); 149 | assertEquals(3, (int) sol.next()); 150 | } 151 | 152 | @Test 153 | public void test2() { 154 | List> test = new ArrayList<>(); 155 | test.add(new ArrayList() {{ 156 | add(1); 157 | add(2); 158 | }}); 159 | test.add(new ArrayList() {{ 160 | add(3); 161 | }}); 162 | test.add(new ArrayList() {{ 163 | add(4); 164 | add(5); 165 | add(6); 166 | }}); 167 | Solution_2 sol = new ListofListIterator().new Solution_2(test); 168 | assertTrue(sol.hasNext()); 169 | assertEquals(1, (int) sol.next()); 170 | sol.remove(); 171 | List res = new ArrayList<>(); 172 | while (sol.hasNext()) { 173 | res.add(sol.next()); 174 | } 175 | assertEquals(5, res.size()); 176 | assertEquals(2, (int) res.get(0)); 177 | assertEquals(4, (int) res.get(2)); 178 | assertEquals(6, (int) res.get(4)); 179 | 180 | test = new ArrayList<>(); 181 | test.add(new ArrayList() {{ 182 | add(1); 183 | add(2); 184 | }}); 185 | test.add(new ArrayList() {{ 186 | add(3); 187 | }}); 188 | sol = new ListofListIterator().new Solution_2(test); 189 | assertTrue(sol.hasNext()); 190 | assertEquals(1, (int) sol.next()); 191 | assertTrue(sol.hasNext()); 192 | assertEquals(2, (int) sol.next()); 193 | sol.remove(); 194 | assertTrue(sol.hasNext()); 195 | assertEquals(3, (int) sol.next()); 196 | } 197 | 198 | } 199 | } 200 | 201 | -------------------------------------------------------------------------------- /src/main/java/maximum_number_of_nights_you_can_accommodate/MaximumNumberofNightsYouCanAccommodate.java: -------------------------------------------------------------------------------- 1 | package maximum_number_of_nights_you_can_accommodate; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class MaximumNumberofNightsYouCanAccommodate { 8 | /* 9 | Maximum Number a Night You Can Accommodate 10 | AirBnB Interview Question 11 | */ 12 | public class Solution { 13 | public int rob(int[] nums) { 14 | if (nums == null) return 0; 15 | int n = nums.length; 16 | if (n == 0) return 0; 17 | if (n == 1) return nums[0]; 18 | 19 | int f1 = nums[0]; // max sof far, excluding current 20 | int f2 = Math.max(nums[0], nums[1]); // max so far 21 | for (int i = 2; i < n; i++) { 22 | int f = Math.max(f1 + nums[i], f2); 23 | f1 = f2; 24 | f2 = f; 25 | } 26 | 27 | return f2; 28 | } 29 | } 30 | 31 | public static class UnitTest { 32 | @Test 33 | public void test1() { 34 | Solution sol = new MaximumNumberofNightsYouCanAccommodate().new Solution(); 35 | int[] test1 = {5, 6, 3, 1}; 36 | assertEquals(8, sol.rob(test1)); 37 | int[] test2 = {6, 5, 0, 1, 0, 9}; 38 | assertEquals(16, sol.rob(test2)); 39 | int[] test3 = {5, 1, 1, 5}; 40 | assertEquals(10, sol.rob(test3)); 41 | int[] test4 = {3, 6, 4}; 42 | assertEquals(7, sol.rob(test4)); 43 | int[] test5 = {4, 10, 3, 1, 5}; 44 | assertEquals(15, sol.rob(test5)); 45 | } 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/meeting_time/MeetingTime.java: -------------------------------------------------------------------------------- 1 | package meeting_time; 2 | 3 | import java.util.*; 4 | 5 | import common.Interval; 6 | import org.junit.*; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | public class MeetingTime { 11 | 12 | /* 13 | Meeting Time 14 | AirBnB Interview Question 15 | */ 16 | public class Solution { 17 | class Point implements Comparable { 18 | int time; 19 | boolean isStart; 20 | 21 | Point(int time, boolean isStart) { 22 | this.time = time; 23 | this.isStart = isStart; 24 | } 25 | 26 | @Override 27 | public int compareTo(Point that) { 28 | if (this.time != that.time || this.isStart == that.isStart) { 29 | return this.time - that.time; 30 | } else { 31 | return this.isStart ? -1 : 1; 32 | } 33 | } 34 | } 35 | 36 | public List getAvailableIntervals(List> intervals, int k) { 37 | List res = new ArrayList<>(); 38 | List points = new ArrayList<>(); 39 | 40 | for (List intervalList : intervals) { 41 | for (Interval interval : intervalList) { 42 | points.add(new Point(interval.start, true)); 43 | points.add(new Point(interval.end, false)); 44 | } 45 | } 46 | Collections.sort(points); 47 | 48 | int count = 0; 49 | Integer availableStart = null; 50 | for (int i = 0; i < points.size(); i++) { 51 | Point point = points.get(i); 52 | if (point.isStart) { 53 | count++; 54 | if (availableStart == null && i == 0 && count <= intervals.size() - k) { 55 | availableStart = point.time; 56 | } else if (availableStart != null && count == intervals.size() - k + 1) { 57 | res.add(new Interval(availableStart, point.time)); 58 | availableStart = null; 59 | } 60 | } else { 61 | count--; 62 | if (count == intervals.size() - k && i < points.size() - 1) { 63 | availableStart = point.time; 64 | } else if (availableStart != null && i == points.size() - 1 && count <= intervals.size() - k) { 65 | res.add(new Interval(availableStart, point.time)); 66 | availableStart = null; 67 | } 68 | } 69 | } 70 | 71 | return res; 72 | } 73 | } 74 | 75 | public static class UnitTest { 76 | @Test 77 | public void test1() { 78 | Solution sol = new MeetingTime().new Solution(); 79 | List> intervals = new ArrayList>() {{ 80 | add(new ArrayList() {{ 81 | add(new Interval(1, 3)); 82 | add(new Interval(6, 7)); 83 | }}); 84 | add(new ArrayList() {{ 85 | add(new Interval(2, 4)); 86 | }}); 87 | add(new ArrayList() {{ 88 | add(new Interval(2, 3)); 89 | add(new Interval(9, 12)); 90 | }}); 91 | }}; 92 | List res = sol.getAvailableIntervals(intervals, 3); 93 | assertEquals(2, res.size()); 94 | assertEquals(4, res.get(0).start); 95 | assertEquals(6, res.get(0).end); 96 | assertEquals(7, res.get(1).start); 97 | assertEquals(9, res.get(1).end); 98 | } 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/main/java/menu_combination_sum/MenuCombinationSum.java: -------------------------------------------------------------------------------- 1 | package menu_combination_sum; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class MenuCombinationSum { 10 | /* 11 | Menu Combination Sum 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private void search(List> res, int[] centsPrices, int start, int centsTarget, 16 | List curCombo, double[] prices) { 17 | if (centsTarget == 0) { 18 | res.add(new ArrayList<>(curCombo)); 19 | return; 20 | } 21 | 22 | for (int i = start; i < centsPrices.length; i++) { 23 | if (i > start && centsPrices[i] == centsPrices[i - 1]) { 24 | continue; 25 | } 26 | if (centsPrices[i] > centsTarget) { 27 | break; 28 | } 29 | curCombo.add(prices[i]); 30 | search(res, centsPrices, i + 1, centsTarget - centsPrices[i], curCombo, prices); 31 | curCombo.remove(curCombo.size() - 1); 32 | } 33 | } 34 | 35 | public List> getCombos(double[] prices, double target) { 36 | List> res = new ArrayList<>(); 37 | if (prices == null || prices.length == 0 || target <= 0) { 38 | return res; 39 | } 40 | 41 | int centsTarget = (int) Math.round(target * 100); 42 | Arrays.sort(prices); 43 | int[] centsPrices = new int[prices.length]; 44 | for (int i = 0; i < prices.length; i++) { 45 | centsPrices[i] = (int) Math.round(prices[i] * 100); 46 | } 47 | 48 | search(res, centsPrices, 0, centsTarget, new ArrayList<>(), prices); 49 | return res; 50 | } 51 | } 52 | 53 | public static class UnitTest { 54 | @Test 55 | public void test1() { 56 | Solution sol = new MenuCombinationSum().new Solution(); 57 | double[] prices = {10.02, 1.11, 2.22, 3.01, 4.02, 2.00, 5.03}; 58 | List> combos = sol.getCombos(prices, 7.03); 59 | System.out.println(combos); 60 | assertEquals(2, combos.size()); 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/minimum_cost_with_at_most_k_stops/MinimumCostwithAtMostKStops.java: -------------------------------------------------------------------------------- 1 | package minimum_cost_with_at_most_k_stops; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class MinimumCostwithAtMostKStops { 10 | /* 11 | Minimum Cost with At Most K Stops - BFS 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public int minCost(List lines, String source, String target, int k) { 16 | if (lines.size() == 0 || k < 0) { 17 | return 0; 18 | } 19 | Map nodes = new HashMap<>(); 20 | for (String line : lines) { 21 | String[] s = line.trim().split(","); 22 | String[] t = s[0].trim().split("->"); 23 | String from = t[0]; 24 | String to = t[1]; 25 | int cost = Integer.valueOf(s[1].trim()); 26 | if (!nodes.containsKey(from)) nodes.put(from, new Flight(from)); 27 | if (!nodes.containsKey(to)) nodes.put(to, new Flight(to)); 28 | nodes.get(from).nextNodes.put(to, cost); 29 | } 30 | 31 | boolean find = false; 32 | Queue q = new LinkedList<>(); 33 | Queue cost = new LinkedList<>(); 34 | q.offer(source); 35 | cost.offer(0); 36 | int stops = -1; 37 | while (!q.isEmpty()) { 38 | stops++; 39 | if (stops > k + 1) { 40 | break; 41 | } 42 | int qSize = q.size(); 43 | for (int i = 0; i < qSize; i++) { 44 | Flight curr = nodes.get(q.poll()); 45 | int currCost = cost.poll(); 46 | curr.minCost = Math.min(curr.minCost, currCost); 47 | 48 | if (curr.name.equals(target)) { 49 | find = true; 50 | continue; 51 | } 52 | 53 | for (String next : curr.nextNodes.keySet()) { 54 | int nextCost = currCost + curr.nextNodes.get(next); 55 | if (nextCost < nodes.get(next).minCost && (stops < k || stops == k && next.equals(target))) { 56 | q.offer(next); 57 | cost.offer(nextCost); 58 | } 59 | } 60 | } 61 | } 62 | 63 | return find ? nodes.get(target).minCost : -1; 64 | } 65 | } 66 | 67 | class Flight { 68 | String name; 69 | int minCost; 70 | Map nextNodes; 71 | 72 | Flight(String name) { 73 | this.name = name; 74 | this.minCost = Integer.MAX_VALUE; 75 | this.nextNodes = new HashMap<>(); 76 | } 77 | } 78 | 79 | 80 | public static class UnitTest { 81 | @Test 82 | public void test1() { 83 | Solution sol = new MinimumCostwithAtMostKStops().new Solution(); 84 | List lines = new ArrayList<>(); 85 | lines.add("A->B,100"); 86 | lines.add("A->C,400"); 87 | lines.add("B->C,100"); 88 | lines.add("C->D,100"); 89 | lines.add("C->A,10"); 90 | assertEquals(-1, sol.minCost(lines, "A", "D", 0)); 91 | assertEquals(500, sol.minCost(lines, "A", "D", 1)); 92 | assertEquals(300, sol.minCost(lines, "A", "D", 2)); 93 | } 94 | } 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/main/java/minimum_vertices_to_traverse_directed_graph/MinimumVerticestoTraverseDirectedGraph.java: -------------------------------------------------------------------------------- 1 | package minimum_vertices_to_traverse_directed_graph; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class MinimumVerticestoTraverseDirectedGraph { 10 | /* 11 | Minimum Vertices to Traverse Directed Graph - DFS 12 | https://cs.stackexchange.com/questions/1698/find-the-minimal-number-of-runs-to-visit-every-edge-of-a-directed-graph 13 | AirBnB Interview Question 14 | */ 15 | public class Solution { 16 | private void search(Set res, Map> nodes, int cur, int start, 17 | Set visited, Set currVisited) { 18 | currVisited.add(cur); 19 | visited.add(cur); 20 | for (int next : nodes.get(cur)) { 21 | if (res.contains(next) && next != start) { 22 | res.remove(next); 23 | } 24 | if (!currVisited.contains(next)) { 25 | search(res, nodes, next, start, visited, currVisited); 26 | } 27 | } 28 | } 29 | 30 | public List getMin(int[][] edges, int n) { 31 | Map> nodes = new HashMap<>(); 32 | for (int i = 0; i < n; i++) { 33 | nodes.put(i, new HashSet<>()); 34 | } 35 | for (int[] edge : edges) { 36 | nodes.get(edge[0]).add(edge[1]); 37 | } 38 | 39 | Set visited = new HashSet<>(); 40 | Set res = new HashSet<>(); 41 | for (int i = 0; i < n; i++) { 42 | if (!visited.contains(i)) { 43 | res.add(i); 44 | visited.add(i); 45 | search(res, nodes, i, i, visited, new HashSet<>()); 46 | } 47 | } 48 | 49 | return new ArrayList<>(res); 50 | } 51 | } 52 | 53 | public static class UnitTest { 54 | @Test 55 | public void test1() { 56 | Solution sol = new MinimumVerticestoTraverseDirectedGraph().new Solution(); 57 | //// 1->2->3->1, 2->0->0 58 | //// 0 1 2 3 59 | //// 0[1, 0, 0, 0] 60 | //// 1[0, 0, 1, 0] 61 | //// 2[1, 0, 0, 1] 62 | //// 3[0, 1, 0, 0] 63 | int[][] edges = {{0, 0}, {1, 2}, {2, 0}, {2, 3}, {3, 1}}; 64 | List res = sol.getMin(edges, 4); 65 | System.out.println(res); 66 | assertEquals(1, res.size()); 67 | 68 | //// 0->1->0, 2->3->2->1 69 | //// 0 1 2 3 70 | //// 0[0, 1, 0, 0] 71 | //// 1[1, 0, 0, 0] 72 | //// 2[0, 1, 0, 1] 73 | //// 3[0, 0, 1, 0] 74 | edges = new int[][]{{0, 1}, {1, 0}, {2, 1}, {2, 3}, {3, 2}}; 75 | res = sol.getMin(edges, 4); 76 | System.out.println(res); 77 | assertEquals(1, res.size()); 78 | 79 | //// 3->2->1->0 0->1 3->1 80 | //// 0 1 2 3 81 | //// 0[0, 1, 0, 0] 82 | //// 1[1, 0, 0, 0] 83 | //// 2[0, 1, 0, 0] 84 | //// 3[0, 1, 1, 0] 85 | edges = new int[][]{{0, 1}, {1, 0}, {2, 1}, {3, 1}, {3, 2}}; 86 | res = sol.getMin(edges, 4); 87 | System.out.println(res); 88 | assertEquals(1, res.size()); 89 | 90 | //// 0 1 2 3 4 5 6 7 8 9 91 | //// 0[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 92 | //// 1[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 93 | //// 2[0, 0, 0 ,0, 0, 0, 0, 0, 0, 1] 94 | //// 3[0, 0, 0, 1, 0, 1, 0, 1, 0, 0] 95 | //// 4[0, 0, 0, 0, 0, 0 ,0, 0, 1, 0] 96 | //// 5[0, 0, 0, 0, 0, 0, 0, 0, 1, 0] 97 | //// 6[0, 0, 0, 0, 0, 0, 1, 0, 0 ,0] 98 | //// 7[0, 0, 0, 0, 1, 0, 0, 0, 0, 0] 99 | //// 8[0, 0, 0, 0, 0, 0, 0, 1, 0, 0] 100 | //// 9[0, 0, 0, 1, 0, 0, 1, 0, 0, 0] 101 | edges = new int[][]{{2, 9}, {3, 3}, {3, 5}, {3, 7}, {4, 8}, {5, 8}, {6, 6}, {7, 4}, {8, 7}, {9, 3}, {9, 6}}; 102 | res = sol.getMin(edges, 10); 103 | System.out.println(res); 104 | assertEquals(3, res.size()); 105 | } 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/main/java/number_of_intersected_rectangles/NumberofIntersectedRectangles.java: -------------------------------------------------------------------------------- 1 | package number_of_intersected_rectangles; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class NumberofIntersectedRectangles { 10 | /* 11 | Number of Intersected Rectangles - Union Find 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private boolean intersect(int[][] r1, int[][] r2) { 16 | return r1[0][0] < r2[0][0] && r1[0][1] < r2[0][1] && r2[0][0] < r1[1][0] && r2[0][1] < r1[1][1] || 17 | r1[0][0] < r2[1][0] && r1[0][1] < r2[1][1] && r2[1][0] < r1[1][0] && r2[1][1] < r1[1][1]; 18 | } 19 | 20 | private int find(int val, int[] parents) { 21 | while (parents[val] != val) { 22 | val = parents[val]; 23 | } 24 | return val; 25 | } 26 | 27 | public int countIntersection(int[][][] rectangles) { 28 | if (rectangles == null || rectangles.length == 0) return 0; 29 | int n = rectangles.length; 30 | int[] parents = new int[n]; 31 | for (int i = 0; i < n; i++) { 32 | parents[i] = i; 33 | } 34 | for (int i = 0; i < n - 1; i++) { 35 | for (int j = i + 1; j < n; j++) { 36 | if (intersect(rectangles[i], rectangles[j])) { 37 | int root1 = find(i, parents); 38 | int root2 = find(j, parents); 39 | 40 | if (root1 != root2) { 41 | parents[root1] = root2; 42 | } 43 | } 44 | } 45 | } 46 | 47 | Set set = new HashSet<>(); 48 | for (int i = 0; i < n; i++) { 49 | set.add(find(i, parents)); 50 | } 51 | 52 | return set.size(); 53 | } 54 | } 55 | 56 | public static class UnitTest { 57 | @Test 58 | public void test1() { 59 | Solution sol = new NumberofIntersectedRectangles().new Solution(); 60 | int[][][] rectangles = { 61 | {{-3, -2}, {2, 1}}, 62 | {{10, 8}, {15, 10}}, 63 | {{1, 0}, {7, 4}}, 64 | {{12, 9}, {16, 12}}, 65 | {{-2, -1}, {5, 3}} 66 | }; 67 | assertEquals(2, sol.countIntersection(rectangles)); 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/palindrome_pairs/PalindromePairs.java: -------------------------------------------------------------------------------- 1 | package palindrome_pairs; 2 | 3 | import java.util.*; 4 | import org.junit.*; 5 | import static org.junit.Assert.*; 6 | 7 | public class PalindromePairs { 8 | /* 9 | Palindrome Pairs - HashMap 10 | AirBnB Interview Question 11 | */ 12 | public class Solution { 13 | private boolean isPalindrome(String s) { 14 | for (int i = 0; i < s.length() / 2; ++i) 15 | if (s.charAt(i) != s.charAt(s.length() - 1 - i)) 16 | return false; 17 | return true; 18 | } 19 | 20 | public List> palindromePairs(String[] words) { 21 | List> res = new ArrayList<>(); 22 | if (words == null) return res; 23 | HashMap map = new HashMap<>(); 24 | for (int i = 0; i < words.length; i++) map.put(words[i], i); 25 | for (int i = 0; i < words.length; i++) { 26 | int left = 0, right = 0; 27 | while (left <= right) { 28 | String s = words[i].substring(left, right); 29 | Integer j = map.get(new StringBuilder(s).reverse().toString()); 30 | if (j != null && i != j && isPalindrome(words[i].substring(left == 0 ? right : 0, left == 0 ? words[i].length() : left))) 31 | res.add(Arrays.asList(left == 0 ? new Integer[]{i, j} : new Integer[]{j, i})); 32 | if (right < words[i].length()) right++; 33 | else left++; 34 | } 35 | } 36 | return res; 37 | } 38 | } 39 | 40 | /* 41 | Palindrome Pairs - Trie 42 | AirBnB Interview Question 43 | */ 44 | public class Solution_2 { 45 | class TrieNode { 46 | TrieNode[] next; 47 | int index; 48 | List list; 49 | 50 | TrieNode() { 51 | next = new TrieNode[26]; 52 | index = -1; 53 | list = new ArrayList<>(); 54 | } 55 | } 56 | 57 | private void addWord(TrieNode root, String word, int index) { 58 | for (int i = word.length() - 1; i >= 0; i--) { 59 | if (root.next[word.charAt(i) - 'a'] == null) { 60 | root.next[word.charAt(i) - 'a'] = new TrieNode(); 61 | } 62 | 63 | if (isPalindrome(word, 0, i)) { 64 | root.list.add(index); 65 | } 66 | 67 | root = root.next[word.charAt(i) - 'a']; 68 | } 69 | 70 | root.list.add(index); 71 | root.index = index; 72 | } 73 | 74 | private boolean isPalindrome(String word, int i, int j) { 75 | while (i < j) { 76 | if (word.charAt(i++) != word.charAt(j--)) return false; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | private void search(String[] words, int i, TrieNode root, List> list) { 83 | for (int j = 0; j < words[i].length(); j++) { 84 | if (root.index >= 0 && root.index != i && isPalindrome(words[i], j, words[i].length() - 1)) { 85 | list.add(Arrays.asList(i, root.index)); 86 | } 87 | 88 | root = root.next[words[i].charAt(j) - 'a']; 89 | if (root == null) return; 90 | } 91 | 92 | for (int j : root.list) { 93 | if (i == j) continue; 94 | list.add(Arrays.asList(i, j)); 95 | } 96 | } 97 | 98 | public List> palindromePairs(String[] words) { 99 | List> res = new ArrayList<>(); 100 | 101 | TrieNode root = new TrieNode(); 102 | for (int i = 0; i < words.length; i++) { 103 | addWord(root, words[i], i); 104 | } 105 | 106 | for (int i = 0; i < words.length; i++) { 107 | search(words, i, root, res); 108 | } 109 | 110 | return res; 111 | } 112 | } 113 | public static class UnitTest { 114 | @Test 115 | public void test1() { 116 | Solution sol = new PalindromePairs().new Solution(); 117 | String[] test = new String[]{"bat", "tab", "cat"}; 118 | List> rslt = sol.palindromePairs(test); 119 | assertEquals(2, rslt.size()); 120 | 121 | test = new String[]{"abcd", "dcba", "lls", "s", "sssll"}; 122 | rslt = sol.palindromePairs(test); 123 | assertEquals(4, rslt.size()); 124 | 125 | test = new String[]{"a", ""}; 126 | rslt = sol.palindromePairs(test); 127 | assertEquals(2, rslt.size()); 128 | } 129 | 130 | @Test 131 | public void test2() { 132 | Solution_2 sol = new PalindromePairs().new Solution_2(); 133 | String[] test = new String[]{"bat", "tab", "cat"}; 134 | List> rslt = sol.palindromePairs(test); 135 | assertEquals(2, rslt.size()); 136 | 137 | test = new String[]{"abcd", "dcba", "lls", "s", "sssll"}; 138 | rslt = sol.palindromePairs(test); 139 | assertEquals(4, rslt.size()); 140 | 141 | test = new String[]{"a", ""}; 142 | rslt = sol.palindromePairs(test); 143 | assertEquals(2, rslt.size()); 144 | } 145 | } 146 | } 147 | 148 | -------------------------------------------------------------------------------- /src/main/java/preference_list/PreferenceList.java: -------------------------------------------------------------------------------- 1 | package preference_list; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class PreferenceList { 10 | /* 11 | Preference List 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public List getPreference(List> preferences) { 16 | Map inDegree = new HashMap<>(); 17 | Map> nodes = new HashMap<>(); 18 | for (List l : preferences) { 19 | for (int i = 0; i < l.size() - 1; i++) { 20 | int from = l.get(i); 21 | int to = l.get(i + 1); 22 | if (!nodes.containsKey(from)) { 23 | inDegree.put(from, 0); 24 | nodes.put(from, new HashSet<>()); 25 | } 26 | if (!nodes.containsKey(to)) { 27 | inDegree.put(to, 0); 28 | nodes.put(to, new HashSet<>()); 29 | } 30 | if (!nodes.get(from).contains(to)) { 31 | Set s = nodes.get(from); 32 | s.add(to); 33 | nodes.put(from, s); 34 | } 35 | inDegree.put(to, inDegree.getOrDefault(to, 0) + 1); 36 | } 37 | } 38 | Queue q = new LinkedList<>(); 39 | for (int k : inDegree.keySet()) { 40 | if (inDegree.get(k) == 0) { 41 | q.offer(k); 42 | } 43 | } 44 | List res = new ArrayList<>(); 45 | while (!q.isEmpty()) { 46 | int id = q.poll(); 47 | res.add(id); 48 | Set neighbors = nodes.get(id); 49 | for (int next : neighbors) { 50 | int degree = inDegree.get(next) - 1; 51 | inDegree.put(next, degree); 52 | if (degree == 0) q.offer(next); 53 | } 54 | } 55 | return res; 56 | } 57 | } 58 | 59 | public static class UnitTest { 60 | @Test 61 | public void test1() { 62 | Solution sol = new PreferenceList().new Solution(); 63 | List> preferences = new ArrayList<>(); 64 | List p1 = new ArrayList() {{ 65 | add(2); 66 | add(3); 67 | add(5); 68 | }}; 69 | List p2 = new ArrayList() {{ 70 | add(4); 71 | add(2); 72 | add(1); 73 | }}; 74 | List p3 = new ArrayList() {{ 75 | add(4); 76 | add(1); 77 | add(5); 78 | add(6); 79 | }}; 80 | List p4 = new ArrayList() {{ 81 | add(4); 82 | add(7); 83 | }}; 84 | preferences.add(p1); 85 | preferences.add(p2); 86 | preferences.add(p3); 87 | preferences.add(p4); 88 | List res = sol.getPreference(preferences); 89 | // System.out.println(res); 90 | assertEquals(7, res.size()); 91 | assertEquals(4, (int) res.get(0)); 92 | assertEquals(2, (int) res.get(1)); 93 | assertEquals(7, (int) res.get(2)); 94 | assertEquals(1, (int) res.get(3)); 95 | assertEquals(3, (int) res.get(4)); 96 | assertEquals(5, (int) res.get(5)); 97 | assertEquals(6, (int) res.get(6)); 98 | 99 | p1 = new ArrayList() {{ 100 | add(3); 101 | add(5); 102 | add(7); 103 | add(9); 104 | }}; 105 | p2 = new ArrayList() {{ 106 | add(2); 107 | add(3); 108 | add(8); 109 | }}; 110 | p3 = new ArrayList() {{ 111 | add(5); 112 | add(8); 113 | }}; 114 | preferences = new ArrayList<>(); 115 | preferences.add(p1); 116 | preferences.add(p2); 117 | preferences.add(p3); 118 | res = sol.getPreference(preferences); 119 | // System.out.println(res); 120 | assertEquals(6, res.size()); 121 | } 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/regular_expression/RegularExpression.java: -------------------------------------------------------------------------------- 1 | package regular_expression; 2 | 3 | import org.junit.*; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class RegularExpression { 8 | /* 9 | Regular Expression 10 | AirBnB Interview Question 11 | */ 12 | public class Solution { 13 | public boolean regMatch(String source, String pattern) { 14 | if (pattern.length() == 0) return source.length() == 0; 15 | if (pattern.length() == 1) { 16 | if (source.length() > 1 || source.length() == 0) return false; 17 | return source.charAt(0) == pattern.charAt(0); 18 | } 19 | 20 | if (source.length() != 0 && (pattern.charAt(0) == '.' || pattern.charAt(0) == source.charAt(0))) { 21 | if (pattern.charAt(1) == '*') { 22 | return regMatch(source.substring(1), pattern) || regMatch(source, pattern.substring(2)); 23 | } else if (pattern.charAt(1) == '+') { 24 | return regMatch(source.substring(1), pattern.substring(2)) || regMatch(source.substring(1), pattern.substring(2)); 25 | } else { 26 | return regMatch(source.substring(1), pattern.substring(1)); 27 | } 28 | } 29 | return pattern.charAt(1) == '*' && regMatch(source, pattern.substring(2)); 30 | } 31 | } 32 | 33 | /* 34 | Regular Expression - Dynamic Programming 35 | AirBnB Interview Question 36 | */ 37 | public class Solution_2 { 38 | public boolean regMatch(String s, String p) { 39 | if (s == null || p == null) return false; 40 | boolean[][] dp = new boolean[p.length() + 1][s.length() + 1]; 41 | dp[0][0] = true; 42 | for (int i = 1; i <= p.length(); i++) { 43 | if (p.charAt(i - 1) == '*' && dp[i - 2][0]) dp[i][0] = true; 44 | } 45 | 46 | for (int i = 1; i <= p.length(); i++) { 47 | for (int j = 1; j <= s.length(); j++) { 48 | if (p.charAt(i - 1) == '.' || p.charAt(i - 1) == s.charAt(j - 1)) { 49 | dp[i][j] = dp[i - 1][j - 1]; 50 | } else if (p.charAt(i - 1) == '*' || p.charAt(i - 1) == '+') { 51 | if (p.charAt(i - 2) == '.' || p.charAt(i - 2) == s.charAt(j - 1)) { 52 | if (p.charAt(i - 1) == '*') { 53 | dp[i][j] = dp[i - 2][j] || dp[i - 2][j - 1] || dp[i][j - 1]; 54 | } else { 55 | dp[i][j] = dp[i - 2][j - 1] || dp[i][j - 1]; 56 | } 57 | } else { 58 | dp[i][j] = p.charAt(i - 1) == '*' && dp[i - 2][j]; 59 | } 60 | } 61 | } 62 | } 63 | return dp[p.length()][s.length()]; 64 | } 65 | } 66 | 67 | public static class UnitTest { 68 | @Test 69 | public void test1() { 70 | Solution sol = new RegularExpression().new Solution(); 71 | assertTrue(sol.regMatch("saaaa", "s+a*")); 72 | assertFalse(sol.regMatch("saaaa", "s+b*")); 73 | assertFalse(sol.regMatch("saaaab", "s+a*")); 74 | assertFalse(sol.regMatch("saaaab", "s+b*")); 75 | } 76 | 77 | @Test 78 | public void test2() { 79 | Solution_2 sol = new RegularExpression().new Solution_2(); 80 | assertTrue(sol.regMatch("saaaa", "s+a*")); 81 | assertFalse(sol.regMatch("saaaa", "s+b*")); 82 | assertFalse(sol.regMatch("saaaab", "s+a*")); 83 | assertFalse(sol.regMatch("saaaab", "s+b*")); 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/main/java/round_prices/RoundPrices.java: -------------------------------------------------------------------------------- 1 | package round_prices; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class RoundPrices { 10 | /* 11 | Round Prices 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public int[] roundUp(double[] arr) { 16 | int n = arr.length; 17 | NumWithDiff[] arrWithDiff = new NumWithDiff[n]; 18 | double sum = 0.0; 19 | int floorSum = 0; 20 | for (int i = 0; i < n; i++) { 21 | int floor = (int) arr[i]; 22 | int ceil = floor; 23 | if (floor < arr[i]) ceil++; 24 | floorSum += floor; 25 | sum += arr[i]; 26 | arrWithDiff[i] = new NumWithDiff(ceil, ceil - arr[i]); 27 | } 28 | 29 | int num = (int) Math.round(sum); 30 | int diff = num - floorSum; 31 | Arrays.sort(arrWithDiff, new Comparator() { 32 | @Override 33 | public int compare(NumWithDiff n1, NumWithDiff n2) { 34 | if (n1.diffWithCeil <= n2.diffWithCeil) return -1; 35 | else return 1; 36 | } 37 | }); 38 | // Arrays.sort(arrWithDiff, (a, b) -> (Double.compare(b.diffWithCeil, a.diffWithCeil))); 39 | 40 | int[] res = new int[n]; 41 | int i = 0; 42 | for (; i < diff; i++) { 43 | res[i] = arrWithDiff[i].num; // 这些放ceil 44 | } 45 | for (; i < n; i++) { 46 | res[i] = arrWithDiff[i].num - 1; // 剩下的只放floor 47 | } 48 | return res; 49 | } 50 | 51 | class NumWithDiff { 52 | int num; 53 | double diffWithCeil; 54 | 55 | public NumWithDiff(int n, double c) { 56 | this.num = n; 57 | this.diffWithCeil = c; 58 | } 59 | } 60 | } 61 | 62 | /* 63 | Round Prices 64 | AirBnB Interview Question 65 | */ 66 | public class Solution_2 { 67 | public int[] roundUp(double[] prices) { 68 | if (prices == null || prices.length == 0) { 69 | return new int[0]; 70 | } 71 | 72 | int[] res = new int[prices.length]; 73 | 74 | double sum = 0; 75 | int roundSum = 0; 76 | Number[] numbers = new Number[prices.length]; 77 | for (int i = 0; i < prices.length; i++) { 78 | numbers[i] = new Number(prices[i], i); 79 | sum += prices[i]; 80 | roundSum += (int) Math.round(prices[i]); 81 | res[i] = (int) Math.round(prices[i]); 82 | } 83 | int sumRound = (int) Math.round(sum); 84 | 85 | if (sumRound == roundSum) { 86 | return res; 87 | } else if (sumRound > roundSum) { 88 | Arrays.sort(numbers, (a, b) -> (Double.compare(b.frac, a.frac))); 89 | int count = sumRound - roundSum; 90 | for (int i = 0; i < prices.length; i++) { 91 | Number num = numbers[i]; 92 | if (num.frac < 0.5 && count > 0) { 93 | res[num.index] = (int) Math.ceil(num.val); 94 | count--; 95 | } else { 96 | res[num.index] = (int) Math.round(num.val); 97 | } 98 | } 99 | } else { 100 | Arrays.sort(numbers, (a, b) -> (Double.compare(a.frac, b.frac))); 101 | int count = roundSum - sumRound; 102 | for (int i = 0; i < prices.length; i++) { 103 | Number num = numbers[i]; 104 | if (num.frac >= 0.5 && count > 0) { 105 | res[num.index] = (int) Math.floor(num.val); 106 | count--; 107 | } else { 108 | res[num.index] = (int) Math.round(num.val); 109 | } 110 | } 111 | } 112 | 113 | return res; 114 | } 115 | 116 | class Number { 117 | double val; 118 | double frac; 119 | int index; 120 | 121 | Number(double val, int index) { 122 | this.val = val; 123 | this.frac = val - Math.floor(val); 124 | this.index = index; 125 | } 126 | } 127 | } 128 | 129 | public static class UnitTest { 130 | @Test 131 | public void test1() { 132 | Solution sol = new RoundPrices().new Solution(); 133 | double[] arr = {1.2, 3.7, 2.3, 4.8}; 134 | int[] res = sol.roundUp(arr); 135 | assertEquals(5, res[0]); 136 | assertEquals(4, res[1]); 137 | assertEquals(2, res[2]); 138 | assertEquals(1, res[3]); 139 | 140 | arr = new double[]{1.2, 2.3, 3.4}; 141 | res = sol.roundUp(arr); 142 | System.out.println(res); 143 | assertEquals(4, res[0]); 144 | assertEquals(2, res[1]); 145 | assertEquals(1, res[2]); 146 | 147 | arr = new double[]{1.2, 3.7, 2.3, 4.8}; 148 | res = sol.roundUp(arr); 149 | assertEquals(5, res[0]); 150 | assertEquals(4, res[1]); 151 | assertEquals(2, res[2]); 152 | assertEquals(1, res[3]); 153 | 154 | arr = new double[]{1.2, 2.5, 3.6, 4.0}; 155 | res = sol.roundUp(arr); 156 | assertEquals(4, res[0]); 157 | assertEquals(3, res[1]); 158 | assertEquals(2, res[2]); 159 | assertEquals(1, res[3]); 160 | } 161 | 162 | @Test 163 | public void test2() { 164 | Solution_2 sol = new RoundPrices().new Solution_2(); 165 | double[] arr = {1.2, 2.3, 3.4}; 166 | int[] res = sol.roundUp(arr); 167 | System.out.println(res); 168 | assertEquals(1, res[0]); 169 | assertEquals(2, res[1]); 170 | assertEquals(4, res[2]); 171 | 172 | arr = new double[]{1.2, 3.7, 2.3, 4.8}; 173 | res = sol.roundUp(arr); 174 | assertEquals(1, res[0]); 175 | assertEquals(4, res[1]); 176 | assertEquals(2, res[2]); 177 | assertEquals(5, res[3]); 178 | 179 | arr = new double[]{1.2, 2.5, 3.6, 4.0}; 180 | res = sol.roundUp(arr); 181 | assertEquals(1, res[0]); 182 | assertEquals(2, res[1]); 183 | assertEquals(4, res[2]); 184 | assertEquals(4, res[3]); 185 | 186 | arr = new double[]{2.5, 2.3, 3.1, 6.5}; 187 | res = sol.roundUp(arr); 188 | assertEquals(2, res[0]); 189 | assertEquals(2, res[1]); 190 | assertEquals(3, res[2]); 191 | assertEquals(7, res[3]); 192 | 193 | arr = new double[]{2.9, 2.3, 1.4, 3, 6}; 194 | res = sol.roundUp(arr); 195 | assertEquals(3, res[0]); 196 | assertEquals(2, res[1]); 197 | assertEquals(2, res[2]); 198 | assertEquals(3, res[3]); 199 | assertEquals(6, res[4]); 200 | 201 | arr = new double[]{-0.4, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3}; 202 | res = sol.roundUp(arr); 203 | assertEquals(0, res[0]); 204 | assertEquals(2, res[1]); 205 | assertEquals(2, res[2]); 206 | assertEquals(2, res[3]); 207 | assertEquals(1, res[4]); 208 | assertEquals(1, res[5]); 209 | assertEquals(1, res[6]); 210 | assertEquals(1, res[7]); 211 | assertEquals(1, res[8]); 212 | assertEquals(1, res[9]); 213 | assertEquals(1, res[10]); 214 | } 215 | } 216 | } 217 | 218 | -------------------------------------------------------------------------------- /src/main/java/simulate_diplomacy/SimulateDiplomacy.java: -------------------------------------------------------------------------------- 1 | package simulate_diplomacy; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | public class SimulateDiplomacy { 13 | 14 | public static class Army implements Comparable { 15 | String name; 16 | String location; 17 | int strength; 18 | 19 | Army(String n, String l) { 20 | this.name = n; 21 | this.location = l; 22 | this.strength = 1; 23 | } 24 | 25 | @Override 26 | public int compareTo(Army a) { 27 | return name.compareTo(a.name); 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return name + " " + (strength == 0 ? "[dead]" : location); 33 | } 34 | } 35 | 36 | public static class Solution { 37 | 38 | List play(List actions) { 39 | List armies = new ArrayList<>(); 40 | Map indexes = new HashMap<>(); 41 | List supports = new ArrayList<>(); 42 | for (String action : actions) { 43 | String[] tokens = action.split(" "); 44 | String name = tokens[0]; 45 | String location = tokens[1]; 46 | Army a = indexes.get(name); 47 | if (a == null) { 48 | a = new Army(name, location); 49 | armies.add(a); 50 | indexes.put(a.name, a); 51 | } 52 | String act = tokens[2]; 53 | switch (act) { 54 | case "Move": 55 | a.location = tokens[3]; 56 | break; 57 | case "Support": 58 | supports.add(new String[] { a.name, tokens[3] }); 59 | break; 60 | } 61 | } 62 | 63 | Map> attacks = new HashMap<>(); 64 | for (Army a : armies) { 65 | attacks.compute(a.location, (s, list) -> { 66 | if (list == null) 67 | list = new ArrayList<>(); 68 | list.add(a); 69 | return list; 70 | }); 71 | } 72 | // Deal with the attacks 73 | for (Map.Entry> e : attacks.entrySet()) { 74 | List list = e.getValue(); 75 | if (list.size() > 1) { 76 | for (Army a : list) { 77 | a.strength = 0; 78 | } 79 | } 80 | } 81 | // Deal with the support, especially the case where the armies receive more than one support 82 | for (String[] sup : supports) { 83 | String s1 = sup[0]; 84 | String s2 = sup[1]; 85 | Army a1 = indexes.get(s1); 86 | Army a2 = indexes.get(s2); 87 | if (a1.strength > 0) { 88 | a2.strength++; 89 | } 90 | } 91 | for (Map.Entry> e : attacks.entrySet()) { 92 | List list = e.getValue(); 93 | if (list.size() > 1) { 94 | int strongest = 0; 95 | int max = Integer.MIN_VALUE; 96 | for (int i = 0; i < list.size(); i++) { 97 | Army temp = list.get(i); 98 | if (temp.strength > max) { 99 | max = temp.strength; 100 | strongest = i; 101 | } else if (temp.strength == max) { 102 | list.get(strongest).strength = 0; 103 | temp.strength = 0; 104 | } 105 | } 106 | } 107 | } 108 | // Sort the list 109 | Collections.sort(armies); 110 | List res = new ArrayList<>(); 111 | for (Army a : armies) { 112 | res.add(a.toString()); 113 | } 114 | return res; 115 | } 116 | } 117 | 118 | public static class UnitTest { 119 | @Test 120 | public void test1() { 121 | List actions = new ArrayList<>(); 122 | actions.add("A Paris Hold"); 123 | actions.add("B Spain Move Paris"); 124 | actions.add("C London Move Paris"); 125 | List res = new Solution().play(actions); 126 | Assert.assertEquals("A [dead]", res.get(0)); 127 | Assert.assertEquals("B [dead]", res.get(1)); 128 | Assert.assertEquals("C [dead]", res.get(2)); 129 | 130 | actions.clear(); 131 | actions.add("A Paris Support B"); 132 | actions.add("B Spain Move Paris"); 133 | actions.add("C London Move Paris"); 134 | List res2 = new Solution().play(actions); 135 | Assert.assertEquals("A [dead]", res2.get(0)); 136 | Assert.assertEquals("B [dead]", res2.get(1)); 137 | Assert.assertEquals("C [dead]", res2.get(2)); 138 | 139 | actions.clear(); 140 | actions.add("A Brussels Support B"); 141 | actions.add("B Spain Move Paris"); 142 | actions.add("C London Move Paris"); 143 | List res3 = new Solution().play(actions); 144 | Assert.assertEquals("A Brussels", res3.get(0)); 145 | Assert.assertEquals("B Paris", res3.get(1)); 146 | Assert.assertEquals("C [dead]", res3.get(2)); 147 | 148 | actions.clear(); 149 | actions.add("A Brussels Support B"); 150 | actions.add("B Spain Move Paris"); 151 | actions.add("C London Move Paris"); 152 | actions.add("D Brussels Hold"); 153 | List res4 = new Solution().play(actions); 154 | Assert.assertEquals("A [dead]", res4.get(0)); 155 | Assert.assertEquals("B [dead]", res4.get(1)); 156 | Assert.assertEquals("C [dead]", res4.get(2)); 157 | Assert.assertEquals("D [dead]", res4.get(3)); 158 | 159 | actions.clear(); 160 | actions.add("A Brussels Support B"); 161 | actions.add("B Spain Move Paris"); 162 | actions.add("C London Move Paris"); 163 | actions.add("D London Support C"); 164 | List res5 = new Solution().play(actions); 165 | Assert.assertEquals("A Brussels", res5.get(0)); 166 | Assert.assertEquals("B [dead]", res5.get(1)); 167 | Assert.assertEquals("C [dead]", res5.get(2)); 168 | Assert.assertEquals("D London", res5.get(3)); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/sliding_game/SlidingGame.java: -------------------------------------------------------------------------------- 1 | package sliding_game; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class SlidingGame { 10 | /* 11 | Sliding Game 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private final int[][] dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; 16 | private int[][] matrix; 17 | private int m; 18 | private int n; 19 | private int originX; 20 | private int originY; 21 | private String recovered; 22 | 23 | public Solution(int[][] matrix) { 24 | this.matrix = matrix; 25 | this.m = matrix.length; 26 | this.n = matrix[0].length; 27 | int[][] recoveredMatrix = new int[m][n]; 28 | for (int i = 0; i < m; i++) { 29 | for (int j = 0; j < n; j++) { 30 | if (matrix[i][j] == 0) { 31 | this.originX = i; 32 | this.originY = j; 33 | } 34 | 35 | recoveredMatrix[i][j] = i * n + j; 36 | } 37 | } 38 | this.recovered = getMatrixString(recoveredMatrix); 39 | } 40 | 41 | public boolean canSolve() { 42 | Queue items = new LinkedList<>(); 43 | Queue matrix = new LinkedList<>(); 44 | Set visited = new HashSet<>(); 45 | 46 | String stringMatrix = getMatrixString(this.matrix.clone()); 47 | items.offer(new int[]{originX, originY}); 48 | matrix.offer(stringMatrix); 49 | visited.add(stringMatrix); 50 | 51 | while (!items.isEmpty()) { 52 | int size = items.size(); 53 | for (int i = 0; i < size; i++) { 54 | int[] curElement = items.poll(); 55 | String curMatrixString = matrix.poll(); 56 | int x = curElement[0]; 57 | int y = curElement[1]; 58 | 59 | if (curMatrixString.equals(recovered)) { 60 | return true; 61 | } 62 | 63 | for (int k = 0; k < dirs.length; k++) { 64 | int xx = x + dirs[k][0]; 65 | int yy = y + dirs[k][1]; 66 | 67 | if (xx < 0 || xx >= m || yy < 0 || yy >= n) { 68 | continue; 69 | } 70 | 71 | int[][] newMatrix = recoverMatrixString(curMatrixString); 72 | int temp = newMatrix[x][y]; 73 | newMatrix[x][y] = newMatrix[xx][yy]; 74 | newMatrix[xx][yy] = temp; 75 | String newMatrixString = getMatrixString(newMatrix); 76 | if (visited.contains(newMatrixString)) { 77 | continue; 78 | } 79 | 80 | items.offer(new int[]{xx, yy}); 81 | matrix.offer(newMatrixString); 82 | visited.add(newMatrixString); 83 | } 84 | } 85 | } 86 | 87 | return false; 88 | } 89 | 90 | public List getSolution() { 91 | String[] pathWord = {"Down", "Right", "Up", "Left"}; 92 | 93 | Queue items = new LinkedList<>(); 94 | Queue matrix = new LinkedList<>(); 95 | Queue> path = new LinkedList<>(); 96 | Set visited = new HashSet<>(); 97 | 98 | String stringMatrix = getMatrixString(this.matrix.clone()); 99 | items.offer(new int[]{originX, originY}); 100 | matrix.offer(stringMatrix); 101 | path.offer(new ArrayList<>()); 102 | visited.add(stringMatrix); 103 | 104 | while (!items.isEmpty()) { 105 | int size = items.size(); 106 | for (int i = 0; i < size; i++) { 107 | int[] curElement = items.poll(); 108 | String curMatrixString = matrix.poll(); 109 | List curPath = path.poll(); 110 | int x = curElement[0]; 111 | int y = curElement[1]; 112 | 113 | if (curMatrixString.equals(recovered)) { 114 | return curPath; 115 | } 116 | 117 | for (int k = 0; k < dirs.length; k++) { 118 | int xx = x + dirs[k][0]; 119 | int yy = y + dirs[k][1]; 120 | 121 | if (xx < 0 || xx >= m || yy < 0 || yy >= n) { 122 | continue; 123 | } 124 | 125 | int[][] newMatrix = recoverMatrixString(curMatrixString); 126 | int temp = newMatrix[x][y]; 127 | newMatrix[x][y] = newMatrix[xx][yy]; 128 | newMatrix[xx][yy] = temp; 129 | String newMatrixString = getMatrixString(newMatrix); 130 | if (visited.contains(newMatrixString)) { 131 | continue; 132 | } 133 | 134 | List newPath = new ArrayList<>(curPath); 135 | newPath.add(pathWord[k]); 136 | 137 | items.offer(new int[]{xx, yy}); 138 | matrix.offer(newMatrixString); 139 | path.offer(newPath); 140 | visited.add(newMatrixString); 141 | } 142 | } 143 | } 144 | 145 | return new ArrayList<>(); 146 | } 147 | 148 | private String getMatrixString(int[][] matrix) { 149 | StringBuilder sb = new StringBuilder(); 150 | for (int i = 0; i < m; i++) { 151 | for (int j = 0; j < n; j++) { 152 | sb.append(matrix[i][j]).append(","); 153 | } 154 | } 155 | return sb.toString(); 156 | } 157 | 158 | private int[][] recoverMatrixString(String str) { 159 | String[] parts = str.split(","); 160 | int[][] res = new int[m][n]; 161 | for (int i = 0; i < m; i++) { 162 | for (int j = 0; j < n; j++) { 163 | res[i][j] = Integer.parseInt(parts[i * n + j]); 164 | } 165 | } 166 | return res; 167 | } 168 | } 169 | 170 | public static class UnitTest { 171 | @Test 172 | public void test1() { 173 | int[][] matrix = { 174 | {3, 1, 4}, 175 | {6, 2, 0}, 176 | {7, 5, 8} 177 | }; 178 | Solution sol = new SlidingGame().new Solution(matrix); 179 | assertTrue(sol.canSolve()); 180 | List res = sol.getSolution(); 181 | System.out.println(res); 182 | assertEquals(11, (int) res.size()); 183 | assertEquals("Left", res.get(0)); 184 | assertEquals("Down", res.get(1)); 185 | assertEquals("Left", res.get(2)); 186 | assertEquals("Up", res.get(3)); 187 | assertEquals("Up", res.get(4)); 188 | assertEquals("Right", res.get(5)); 189 | assertEquals("Right", res.get(6)); 190 | assertEquals("Down", res.get(7)); 191 | assertEquals("Left", res.get(8)); 192 | assertEquals("Up", res.get(9)); 193 | assertEquals("Left", res.get(10)); 194 | } 195 | } 196 | } 197 | 198 | -------------------------------------------------------------------------------- /src/main/java/string_pyramids_transition_matrix/StringPyramidsTransitionMatrix.java: -------------------------------------------------------------------------------- 1 | package string_pyramids_transition_matrix; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class StringPyramidsTransitionMatrix { 10 | /* 11 | String Pyramids Transition Matrix 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | Map> map; 16 | private Map cache; 17 | final String SEP = "###"; 18 | 19 | Solution(String[] line) { 20 | cache = new HashMap<>(); 21 | map = new HashMap<>(); 22 | for (String s : line) { 23 | String[] splitted = s.split(","); 24 | String key = splitted[0] + SEP + splitted[1]; 25 | Set set = new HashSet<>(); 26 | for (char c : splitted[2].toCharArray()) 27 | set.add(c); 28 | map.put(key, set); 29 | } 30 | } 31 | 32 | private void getNextLevel(List res, String curr, int start, StringBuilder sb) { 33 | if (start == curr.length() - 1) { 34 | res.add(new String(sb)); 35 | return; 36 | } 37 | for (int i = start; i < curr.length() - 1; i++) { 38 | String key = curr.charAt(i) + SEP + curr.charAt(i + 1); 39 | for (char c : map.get(key)) { 40 | sb.append(c); 41 | getNextLevel(res, curr, start + 1, sb); 42 | sb.setLength(sb.length() - 1); 43 | } 44 | } 45 | } 46 | 47 | private boolean search(String input, String current) { 48 | if (cache.containsKey(input)) return cache.get(input); 49 | if (current.length() == 1) { 50 | cache.put(current, input.contains(current)); 51 | return cache.get(current); 52 | } 53 | 54 | List cands = new ArrayList<>(); 55 | getNextLevel(cands, current, 0, new StringBuilder()); 56 | for (String cand : cands) { 57 | // System.out.println(cand); 58 | if (cache.containsKey(cand)) return cache.get(cand); 59 | boolean res = search(input, cand); 60 | if (res) { 61 | cache.put(cand, true); 62 | return true; 63 | } 64 | } 65 | 66 | return false; 67 | } 68 | 69 | public boolean check(String input) { 70 | cache.clear(); 71 | return search(input, input); 72 | } 73 | } 74 | 75 | public static class UnitTest { 76 | @Test 77 | public void test1() { 78 | String[] lines = { 79 | "A,A,AC", "A,B,CD", "A,C,D", "A,D,B", 80 | "B,A,B", "B,B,C", "B,C,A", "B,D,CD", 81 | "C,A,A", "C,B,C", "C,C,D", "C,D,B", 82 | "D,A,BC", "D,B,D", "D,C,A", "D,D,C" 83 | }; 84 | Solution sol = new StringPyramidsTransitionMatrix().new Solution(lines); 85 | // sol.check("ABCD"); 86 | assertTrue(sol.check("ABCD")); 87 | assertTrue(sol.check("AACC")); 88 | assertTrue(sol.check("AAAA")); 89 | assertFalse(sol.check("CCCC")); 90 | assertFalse(sol.check("DDDD")); 91 | } 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/main/java/ten_wizards/TenWizards.java: -------------------------------------------------------------------------------- 1 | package ten_wizards; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class TenWizards { 10 | /* 11 | Ten Wizards - BFS 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public List getShortestPath(List> wizards, int source, int target) { 16 | int n = wizards.size(); 17 | int[] parents = new int[wizards.size()]; 18 | Map map = new HashMap<>(); 19 | for (int i = 0; i < n; i++) { 20 | parents[i] = i; 21 | map.put(i, new Wizard(i)); 22 | } 23 | 24 | map.get(source).dist = 0; 25 | Queue queue = new LinkedList<>(); 26 | queue.offer(map.get(source)); 27 | while (!queue.isEmpty()) { 28 | Wizard curr = queue.poll(); 29 | List neighbors = wizards.get(curr.id); 30 | for (int neighbor : neighbors) { 31 | Wizard next = map.get(neighbor); 32 | int weight = (int) Math.pow(next.id - curr.id, 2); 33 | if (curr.dist + weight < next.dist) { 34 | parents[next.id] = curr.id; 35 | next.dist = curr.dist + weight; 36 | // queue.offer(next); 37 | } 38 | queue.offer(next); 39 | } 40 | } 41 | 42 | List res = new ArrayList<>(); 43 | int t = target; 44 | while (t != source) { 45 | res.add(t); 46 | t = parents[t]; 47 | } 48 | res.add(source); 49 | 50 | Collections.reverse(res); 51 | return res; 52 | } 53 | } 54 | 55 | class Wizard implements Comparable { 56 | int id; 57 | int dist; 58 | // Map costs; 59 | 60 | Wizard(int id) { 61 | this.id = id; 62 | this.dist = Integer.MAX_VALUE; 63 | // this.costs = new HashMap<>(); 64 | } 65 | 66 | @Override 67 | public int compareTo(Wizard that) { 68 | return this.dist - that.dist; 69 | } 70 | } 71 | 72 | /* 73 | Ten Wizards - Dijkstra 74 | AirBnB Interview Question 75 | */ 76 | public class Solution_2 { 77 | public List getShortestPath(List> wizards, int source, int target) { 78 | if (wizards == null || wizards.size() == 0) return null; 79 | int n = wizards.size(); 80 | int[] parent = new int[n]; 81 | Map map = new HashMap<>(); 82 | for (int i = 0; i < n; i++) { 83 | parent[i] = i; 84 | map.put(i, new Wizard(i)); 85 | } 86 | 87 | map.get(source).dist = 0; 88 | Queue pq = new PriorityQueue<>(n); 89 | pq.offer(map.get(source)); 90 | while (!pq.isEmpty()) { 91 | Wizard curr = pq.poll(); 92 | List neighbors = wizards.get(curr.id); 93 | for (int neighbor : neighbors) { 94 | Wizard next = map.get(neighbor); 95 | int weight = (int) Math.pow(next.id - curr.id, 2); 96 | if (curr.dist + weight < next.dist) { 97 | parent[next.id] = curr.id; 98 | pq.remove(next); 99 | next.dist = curr.dist + weight; 100 | pq.offer(next); 101 | } 102 | } 103 | } 104 | 105 | List res = new ArrayList<>(); 106 | int t = target; 107 | while (t != source) { 108 | res.add(t); 109 | t = parent[t]; 110 | } 111 | res.add(source); 112 | Collections.reverse(res); 113 | return res; 114 | } 115 | } 116 | 117 | public static class UnitTest { 118 | @Test 119 | public void test1() { 120 | Solution sol = new TenWizards().new Solution(); 121 | int[][] ids = {{1, 5, 9}, {2, 3, 9}, {4}, {}, {}, {9}, {}, {}, {}, {}}; 122 | List> wizards = new ArrayList<>(); 123 | for (int i = 0; i < ids.length; i++) { 124 | List wizard = new ArrayList<>(); 125 | for (int j = 0; j < ids[i].length; j++) { 126 | wizard.add(ids[i][j]); 127 | } 128 | wizards.add(wizard); 129 | } 130 | List res = sol.getShortestPath(wizards, 0, 9); 131 | assertEquals(3, res.size()); 132 | assertEquals(0, (int) res.get(0)); 133 | assertEquals(5, (int) res.get(1)); 134 | assertEquals(9, (int) res.get(2)); 135 | } 136 | 137 | @Test 138 | public void test2() { 139 | Solution_2 sol = new TenWizards().new Solution_2(); 140 | int[][] ids = {{1, 5, 9}, {2, 3, 9}, {4}, {}, {}, {9}, {}, {}, {}, {}}; 141 | List> wizards = new ArrayList<>(); 142 | for (int i = 0; i < ids.length; i++) { 143 | List wizard = new ArrayList<>(); 144 | for (int j = 0; j < ids[i].length; j++) { 145 | wizard.add(ids[i][j]); 146 | } 147 | wizards.add(wizard); 148 | } 149 | List res = sol.getShortestPath(wizards, 0, 9); 150 | assertEquals(3, res.size()); 151 | assertEquals(0, (int) res.get(0)); 152 | assertEquals(5, (int) res.get(1)); 153 | assertEquals(9, (int) res.get(2)); 154 | } 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /src/main/java/travel_buddy/TravelBuddy.java: -------------------------------------------------------------------------------- 1 | package travel_buddy; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class TravelBuddy { 10 | /* 11 | Travel Buddy 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | private List buddies; 16 | private Set myWishList; 17 | 18 | public Solution(Set myWishList, Map> friendsWishList) { 19 | this.buddies = new ArrayList<>(); 20 | this.myWishList = myWishList; 21 | for (String name : friendsWishList.keySet()) { 22 | Set wishList = friendsWishList.get(name); 23 | Set intersection = new HashSet<>(wishList); 24 | intersection.retainAll(myWishList); 25 | int similarity = intersection.size(); 26 | if (similarity >= wishList.size() / 2) { 27 | buddies.add(new Buddy(name, similarity, wishList)); 28 | } 29 | } 30 | } 31 | 32 | public List getSortedBuddies() { 33 | Collections.sort(buddies); 34 | List res = new ArrayList<>(buddies); 35 | return res; 36 | } 37 | 38 | public List recommendCities(int k) { 39 | List res = new ArrayList<>(); 40 | List buddies = getSortedBuddies(); 41 | 42 | int i = 0; 43 | while (k > 0 && i < buddies.size()) { 44 | Set diff = new HashSet<>(buddies.get(i).wishList); 45 | diff.removeAll(myWishList); 46 | if (diff.size() <= k) { 47 | res.addAll(diff); 48 | k -= diff.size(); 49 | i++; 50 | } else { 51 | Iterator it = diff.iterator(); 52 | while (k > 0) { 53 | res.add(it.next()); 54 | k--; 55 | } 56 | } 57 | } 58 | 59 | return res; 60 | } 61 | 62 | class Buddy implements Comparable { 63 | String name; 64 | int similarity; 65 | Set wishList; 66 | 67 | Buddy(String name, int similarity, Set wishList) { 68 | this.name = name; 69 | this.similarity = similarity; 70 | this.wishList = wishList; 71 | } 72 | 73 | @Override 74 | public int compareTo(Buddy that) { 75 | return that.similarity - this.similarity; 76 | } 77 | } 78 | } 79 | 80 | public static class UnitTest { 81 | @Test 82 | public void test1() { 83 | Set myWishList = new HashSet<>(Arrays.asList(new String[]{"a", "b", "c", "d"})); 84 | Set wishList1 = new HashSet<>(Arrays.asList(new String[]{"a", "b", "e", "f"})); 85 | Set wishList2 = new HashSet<>(Arrays.asList(new String[]{"a", "c", "d", "g"})); 86 | Set wishList3 = new HashSet<>(Arrays.asList(new String[]{"c", "f", "e", "g"})); 87 | Map> friendWishLists = new HashMap<>(); 88 | friendWishLists.put("Buddy1", wishList1); 89 | friendWishLists.put("Buddy2", wishList2); 90 | friendWishLists.put("Buddy3", wishList3); 91 | Solution sol = new TravelBuddy().new Solution(myWishList, friendWishLists); 92 | List res = sol.recommendCities(10); 93 | assertEquals(3, res.size()); 94 | assertEquals("g", res.get(0)); 95 | assertEquals("e", res.get(1)); 96 | assertEquals("f", res.get(2)); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/main/java/water_land/WaterLand.java: -------------------------------------------------------------------------------- 1 | package water_land; 2 | 3 | import java.util.*; 4 | 5 | import org.junit.*; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | public class WaterLand { 10 | /* 11 | Water Land / Water Drop / Pour Water 12 | AirBnB Interview Question 13 | */ 14 | public class Solution { 15 | public void pourWater(int[] heights, int location, int water) { 16 | int[] waters = new int[heights.length]; 17 | int pourLocation; 18 | 19 | while (water > 0) { 20 | int left = location - 1; 21 | while (left >= 0) { 22 | if (heights[left] + waters[left] > heights[left + 1] + waters[left + 1]) { 23 | break; 24 | } 25 | left--; 26 | } 27 | if (heights[left + 1] + waters[left + 1] < heights[location] + waters[location]) { 28 | pourLocation = left + 1; 29 | waters[pourLocation]++; 30 | water--; 31 | continue; 32 | } 33 | 34 | int right = location + 1; 35 | while (right < heights.length) { 36 | if (heights[right] + waters[right] > heights[right - 1] + waters[right - 1]) { 37 | break; 38 | } 39 | right++; 40 | } 41 | if (heights[right - 1] + waters[right - 1] < heights[location] + waters[location]) { 42 | pourLocation = right - 1; 43 | waters[pourLocation]++; 44 | water--; 45 | continue; 46 | } 47 | 48 | pourLocation = location; 49 | waters[pourLocation]++; 50 | water--; 51 | } 52 | 53 | print(heights, waters); 54 | } 55 | 56 | private void print(int[] heights, int[] waters) { 57 | int n = heights.length; 58 | 59 | int maxHeight = 0; 60 | for (int i = 0; i < n; i++) { 61 | maxHeight = Math.max(maxHeight, heights[i] + waters[i]); 62 | } 63 | 64 | for (int height = maxHeight; height >= 0; height--) { 65 | for (int i = 0; i < n; i++) { 66 | if (height <= heights[i]) { 67 | System.out.print("+"); 68 | } else if (height > heights[i] && height <= heights[i] + waters[i]) { 69 | System.out.print("W"); 70 | } else { 71 | System.out.print(" "); 72 | } 73 | } 74 | System.out.println(); 75 | } 76 | System.out.println(); 77 | } 78 | } 79 | 80 | public static class UnitTest { 81 | @Test 82 | public void test1() { 83 | Solution sol = new WaterLand().new Solution(); 84 | int[] waterLand = new int[]{5, 4, 2, 1, 2, 3, 2, 1, 0, 1, 2, 4}; 85 | sol.pourWater(waterLand, 5, 1); 86 | sol.pourWater(waterLand, 5, 5); 87 | sol.pourWater(waterLand, 5, 10); 88 | sol.pourWater(waterLand, 5, 20); 89 | sol.pourWater(waterLand, 5, 30); 90 | sol.pourWater(waterLand, 5, 50); 91 | sol.pourWater(waterLand, 5, 100); 92 | 93 | waterLand = new int[]{5, 4, 2, 1, 3, 2, 2, 1, 0, 1, 4, 3}; 94 | sol.pourWater(waterLand, 4, 1); 95 | sol.pourWater(waterLand, 4, 5); 96 | sol.pourWater(waterLand, 4, 10); 97 | sol.pourWater(waterLand, 4, 20); 98 | sol.pourWater(waterLand, 4, 30); 99 | sol.pourWater(waterLand, 4, 50); 100 | sol.pourWater(waterLand, 4, 100); 101 | } 102 | } 103 | } 104 | 105 | --------------------------------------------------------------------------------