Earlier today I was going to work on a different LeetCode problem, but when I did a search on “alien” two problems were selected. Since one was flagged **Easy** and the second **Hard**, I thought some items might apply from the first one to the second problem. Hopefully it would not take too long to solve the Easy problem so I could tackle the Hard after the end of the workday. **Boy was I mistaken.**

In this post I will refer to LeetCode 953 Verifying an Alien Dictionary, which I was not able to solve as expected. I will proceed as I always and will explain my code which **has not been accepted**. In addition I also copied from LeetCode two additional solutions. I tested them on LeetCode and they are both accepted.

I will attempt to solve the problem on my computer. When done I will copy and paste my code on the LeetCode site. Will then test it and hopefully submit it. The first test example out of three provided by LeetCode **was rejected**.

I will attempt to solve this problem using Java on a Windows 10 computer using the VSCode IDE.

In an alien language, surprisingly they also use english lowercase letters, but possibly in a different order. The order of the alphabet is some permutation of lowercase letters. Given a sequence of words written in the alien language, and the order of the alphabet, return true if and only if the given words are sorted lexicographically in this alien language. Constraints: o 1 <= words.length <= 100 o 1 <= words[i].length <= 20 o order.length == 26 o All characters in words[i] and order are English lowercase letters.

The problem seems to be pretty straightforward. We are given a set of words and we need to check the words until we find one that is not in ascending sorted lexicographically order. In other words if we are provided two words the first should be in a lower place than the second. If we are provided three words, the first would be in the lowest order, followed by the second in a higher (or same) level, and the third word would be the highest of the set.

public boolean isAlienSorted(String[] words, String order) { }

The signature for the method we need to implement is clear. We get a list of words in alien language followed by the alphabet indicating the order and we need to return **true** if the words are or **false** if not in sorted lexicographically order.

hello,leetcode hlabcdefgijkmnopqrstuvwxyz main <<< words: [hello, leetcode] main <<< order: hlabcdefgijkmnopqrstuvwxyz main <<< words[0].compareTo(words[1]): -4 main <<< i: 0 h,l main <<< diff: -4 main <<< i: 1 e,e main <<< diff: 0 main <<< i: 2 l,e main <<< diff: 7 main <<< i: 3 l,t main <<< diff: -8 main <<< i: 4 o,c main <<< diff: 12 <<< hm: {a=2, b=3, c=4, d=5, e=6, f=7, g=8, h=0, i=9, j=10, k=11, l=1, m=12, n=13, o=14, p=15, q=16, r=17, s=18, t=19, u=20, v=21, w=22, x=23, y=24, z=25} <<< ca1: [h, e, l, l, o] <<< ca2: [l, e, e, t, c, o, d, e] <<< j: 0 0 <= 1 <<< j: 1 6 <= 6 <<< j: 2 1 <= 6 <<< j: 3 1 <= 19 <<< j: 4 14 > 4 <<< 14 > 4 main <<< isAlienSorted: false main <<< isAlienSorted1: true main <<< isAlienSorted2: true hello,leetcode abcdefghijklmnopqrstuvwxyz main <<< words: [hello, leetcode] main <<< order: abcdefghijklmnopqrstuvwxyz main <<< words[0].compareTo(words[1]): -4 main <<< i: 0 h,l main <<< diff: -4 main <<< i: 1 e,e main <<< diff: 0 main <<< i: 2 l,e main <<< diff: 7 main <<< i: 3 l,t main <<< diff: -8 main <<< i: 4 o,c main <<< diff: 12 <<< hm: {a=0, b=1, c=2, d=3, e=4, f=5, g=6, h=7, i=8, j=9, k=10, l=11, m=12, n=13, o=14, p=15, q=16, r=17, s=18, t=19, u=20, v=21, w=22, x=23, y=24, z=25} <<< ca1: [h, e, l, l, o] <<< ca2: [l, e, e, t, c, o, d, e] <<< j: 0 7 <= 11 <<< j: 1 4 <= 4 <<< j: 2 11 > 4 <<< 11 > 4 main <<< isAlienSorted: false main <<< isAlienSorted1: true main <<< isAlienSorted2: true word,world,row worldabcefghijkmnpqstuvxyz main <<< words: [word, world, row] main <<< order: worldabcefghijkmnpqstuvxyz main <<< words[0].compareTo(words[1]): -8 main <<< i: 0 w,w main <<< diff: 0 main <<< i: 1 o,o main <<< diff: 0 main <<< i: 2 r,r main <<< diff: 0 main <<< i: 3 d,l main <<< diff: -8 <<< hm: {a=5, b=6, c=7, d=4, e=8, f=9, g=10, h=11, i=12, j=13, k=14, l=3, m=15, n=16, o=1, p=17, q=18, r=2, s=19, t=20, u=21, v=22, w=0, x=23, y=24, z=25} <<< ca1: [w, o, r, d] <<< ca2: [w, o, r, l, d] <<< j: 0 0 <= 0 <<< j: 1 1 <= 1 <<< j: 2 2 <= 2 <<< j: 3 4 > 3 <<< 4 > 3 main <<< isAlienSorted: false main <<< isAlienSorted1: false main <<< isAlienSorted2: false apple,app abcdefghijklmnopqrstuvwxyz main <<< words: [apple, app] main <<< order: abcdefghijklmnopqrstuvwxyz main <<< words[0].compareTo(words[1]): 2 main <<< i: 0 a,a main <<< diff: 0 main <<< i: 1 p,p main <<< diff: 0 main <<< i: 2 p,p main <<< diff: 0 <<< hm: {a=0, b=1, c=2, d=3, e=4, f=5, g=6, h=7, i=8, j=9, k=10, l=11, m=12, n=13, o=14, p=15, q=16, r=17, s=18, t=19, u=20, v=21, w=22, x=23, y=24, z=25} <<< ca1: [a, p, p, l, e] <<< ca2: [a, p, p] <<< j: 0 0 <= 0 <<< j: 1 15 <= 15 <<< j: 2 15 <= 15 main <<< isAlienSorted: false main <<< isAlienSorted1: false main <<< isAlienSorted2: false

We are provided with two input lines. The first is the list of words and the second the order of the letters in the alien dictionary.

Our test code seems to read the provided input and return an array of words and the dictionary.

Please disregard all output until the last three lines. It seems we have three functions that attempt to solve the problem at hand. The first is my solution. The other two are calls to methods accepted by LeetCode. There seems to be an issue with my approach.

Please note that the second test case contains the same two words, and incredibly the order of characters in the dictionary matches ours. **Go figure!**

Note that the last three lines flag the two words “**hello**” and “**leetcode**” as not in sorted lexicographically order.

The other two test cases seem to match in all three implementations.

/** * Test scaffolding. * * !!! NOT PART OF THE SOLUTION !!! */ public static void main(String[] args) throws IOException { // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read alien words **** String[] words = br.readLine().trim().split(","); // **** read dictionary **** String order = br.readLine().trim(); // **** close buffered reader **** br.close(); // ???? ???? System.out.println("main <<< words: " + Arrays.toString(words)); System.out.println("main <<< order: " + order); System.out.println("main <<< words[0].compareTo(words[1]): " + words[0].compareTo(words[1])); for (int i = 0; i < Math.min(words[0].length(), words[1].length()); i++) { // ???? ???? int v1 = words[0].charAt(i); int v2 = words[1].charAt(i); int diff = v1 - v2; // ???? ???? System.out.println("main <<< i: " + i + " " + words[0].charAt(i) + "," + words[1].charAt(i)); System.out.println("main <<< diff: " + diff); } // **** check and display result **** System.out.println("main <<< isAlienSorted: " + isAlienSorted(words, order)); // **** check and display result **** System.out.println("main <<< isAlienSorted1: " + isAlienSorted1(words, order)); // **** check and display result **** System.out.println("main <<< isAlienSorted2: " + isAlienSorted2(words, order)); }

As we assumed earlier, our test code reads the two input lines. The set of words are placed in an array and the dictionary in a string.

Let’s skip to the last three statements. They make calls to three different methods and the results are displayed.

At this point let’s take a look at the code labeled with “????” strings.

We display the list of words which in the first two test cases are “hello” and “leetcode”. We then display the dictionary.

The next line displays the results of comparing the two words. Note that we get as a result -4 on both test cases. Since the Java language understands English but not alien, it compares the two words character by character checking for the same value until the length of the shortest string. The first two letters to be compared are ‘**h**’ and ‘**l**’ which in English (actually ASCII) map to **104** and **108** respectively. Note than 104 -108 = -4 which happens to be the value returned by the String.compareTo() method. Since the first two characters **DO NOT MATCH**, the method returns -4.

We then enter a loop in which we will traverse the first two (and only two) strings character by character until we reach the length of the shortest word.

For each character we extract the value (in ASCII) and compute the difference. We then display the location of the characters in the respective strings, and the associated characters followed on a second line by the difference between the values.

Once again, note that the comparisons are not based on the alien alphabet but on the ASCII values using our English alphabet.

Let’s now concentrate only on the values of diff. The values are the difference of the corresponding characters in the string. If diff is **negative** or **zero**, it indicates that the first string is lexicographically in a lower level than the second because ‘h’ < ‘l’, ‘e’ == ‘e’, and ‘l’ > ‘e’. This implies that these two words are NOT in lexicographical order using the ASCII character set.

/** * Return true if and only if the given words * are sorted lexicographicaly in this alien language. * * !!!! My solution rejected by LeetCode !!!! */ static boolean isAlienSorted(String[] words, String order) { // **** sanity checks **** if (words.length < 2) return true; // **** initialization **** char[] chars = order.toCharArray(); HashMap<Character, Integer> hm = new HashMap<>(); for (int i = 0; i < chars.length; i++) { hm.put(chars[i], i); // hm.put(chars[i], 97 + i); } // ???? ???? System.out.println("<<< hm: " + hm.toString()); // **** traverse array of words comparing adjacent words ~O(2m)**** for (int i = 0; i < words.length - 1; i++) { // **** for ease of use **** char[] ca1 = words[i].toCharArray(); char[] ca2 = words[i + 1].toCharArray(); // ???? ???? System.out.println("<<< ca1: " + Arrays.toString(ca1)); System.out.println("<<< ca2: " + Arrays.toString(ca2)); // **** compare adjacent words ~O(n)**** for (int j = 0; j < Math.min(ca1.length, ca2.length); j++) { // ???? ???? if (hm.get(ca1[j]) <= hm.get(ca2[j])) System.out.println("<<< j: " + j + " " + hm.get(ca1[j]) + " <= " + hm.get(ca2[j])); else System.out.println("<<< j: " + j + " " + hm.get(ca1[j]) + " > " + hm.get(ca2[j])); // **** compare characters **** if (hm.get(ca1[j]) > hm.get(ca2[j])) { // ???? ???? System.out.println("<<< " + hm.get(ca1[j]) + " > " + hm.get(ca2[j])); // **** **** return false; } } // **** compare word length **** if (ca1.length > ca2.length) return false; } // **** words are in scending order **** return true; }

We start by performing a sanity check. We then initialize a hash map with the characters of the alien dictionary associating each with their order. The first character gets a 0, the second character a 1, and so forth. The hash map is then displayed.

In the first example we can see that ‘h’ is assigned 0, ‘l’ is assigned 1, ‘a’ is assigned 2, and so forth. This is identical to what we so in English with the only difference that ASCII ‘a’ has an assigned value of 97. By assigning an offset of 97 to all lowercase characters **the difference between characters is not changed**.

We now enter a loop in which we will compare two consecutive strings. The idea is that if we find a string that is out of order we will return a false. If all strings match we should return true with a consideration which we will discuss shortly.

We extract the characters from the two strings in question into two character arrays. The strings are then displayed so we can follow the process.

Now we enter a loop to check corresponding characters. Since the strings need to be in lexicographical order if the first string has a character with a larger value than the second one, we should return **false**. Note that we cannot exit after the first or second, or third character. We need to check all associated characters. We will take care of strings with different lengths shortly after.

In our second test case we see that ‘hello’ and ‘leetcode’ maintain the expected association for the letters ‘hell’ (smaller values) and ‘leet’ (same or larger values). When we reach the fifth set of characters, we compare ‘o’ with ‘c’. This time, ‘o’ is larger than ‘c’ so we return **false**. This is with **ASCII** values.

Back to our first example, we compare ‘hell’ and ‘leet’ and the **alien character** set cooperates as illustrated. But when we reach the fifth set of characters we have ‘o’ with a value of 14 and ‘c’ with a value of 4. Since 14 > 4 we need to return **false**.

That is my case. I must be missing something in my interpretation of the problem because my solution returns **false** while LeetCode expects **true**.

/** * Return true if and only if the given words * are sorted lexicographicaly in this alien language. * * Solution accepted by LeetCode. */ static boolean isAlienSorted1(String[] words, String order) { // **** **** int[] index = new int[26]; for (int i = 0; i < order.length(); ++i) index[order.charAt(i) - 'a'] = i; // ???? ???? // System.out.println("<<< index: " + Arrays.toString(index)); // **** **** search: for (int i = 0; i < words.length - 1; ++i) { String word1 = words[i]; String word2 = words[i+1]; // ???? ???? // System.out.println("<<< word1: " + word1); // System.out.println("<<< word2: " + word2); // Find the first difference word1[k] != word2[k]. for (int k = 0; k < Math.min(word1.length(), word2.length()); ++k) { // ???? ???? // System.out.println("<<< " + word1.charAt(k) + " != " + word2.charAt(k)); // **** **** if (word1.charAt(k) != word2.charAt(k)) { // ???? ???? // System.out.println("<<< " + index[word1.charAt(k) - 'a'] + " > " + // index[word2.charAt(k) - 'a']); // If they compare badly, it's not sorted. if (index[word1.charAt(k) - 'a'] > index[word2.charAt(k) - 'a']) return false; continue search; } } // **** if we didn't find a first difference, the words are like ("app", "apple") **** if (word1.length() > word2.length()) return false; } // **** words in ascending order **** return true; }

I copied this solution from the LeetCode web site. This implementation returns **true** on the first two test cases.

/** * Return true if and only if the given words * are sorted lexicographicaly in this alien language. * * Solution accepted by LeetCode. */ static boolean isAlienSorted2(String[] words, String order) { // **** **** if (words == null || words.length == 0 || order == null || order.length() == 0) return false; // **** **** Comparator<String> comparator = new Comparator<String>(){ @Override public int compare(String str1, String str2) { for (int i = 0; i < Math.min(str1.length(), str2.length()); i++) { char a = str1.charAt(i), b = str2.charAt(i); if (a != b) { if (order.indexOf(a) > order.indexOf(b)) return 1; else return -1; } } if (str1.length() > str2.length()) return 1; else if (str1.length() == str2.length()) return 0; else return -1; } }; PriorityQueue<String> pq = new PriorityQueue<>(words.length, comparator); for (String s: words) pq.offer(s); int index = 0; // **** **** while (!pq.isEmpty()) { if (!pq.poll().equals(words[index++])) return false; } return true; }

I also copied this solution from LeetCode. This implementation also returns **true** on the first two cases.

Hope you enjoyed solving this problem as much as I did. The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to help out with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a private e-mail message. I will reply as soon as possible.

Keep on reading and experimenting. It is one of the best ways to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all **6,134** subscribers to this blog!!!

Keep safe during the COVID-19 pandemic and help restart the world economy. I believe we can all see the light at the end of the tunnel.

Regards;

John

**john.canessa@gmail.com**

Yesterday my wife and I made a couple Neapolitan pizzas that were **quite close** to the original ones. I am not going to go into the ingredients at this time. The technique resides in how the pizza is cooked. In general, in the USA we do not have pizza ovens in our backyards. A pizza brick oven heats up north of 600F which is not possible to achieve in a regular home oven. In addition, the initial transfer of heat, due to the size of the oven, is not possible. So, by reading and watching videos, we ended up with the following set of steps:

1. Preheat oven to 550F (takes about 15 minutes in our convection Thermador oven) 2. Add some olive oil to a large (14 to 15 inch cast iron pan) 3. Carefully place the dough on the cast iron pan 4. Turn on your largest gas burner on your range (we have a Viking with high heating capacity) 5. The first pizza will take about 7 minutes to cook (the following ones will take about 5) 6. Carefully move the pan into the oven 7. Finish cooking the pizza in about 7 to 8 minutes 8. Carefully remove the pan from the oven 9. Move the pizza from the pan to a tray and let it rest for 5 minutes (if you can) 10. Use a cutting wheel to cut 6 slices 11. Enjoy!!!

If you try this cooking technique, please share the experience with others. In general I enjoy reading and experimenting, not only with technical topics and subjects, but in general to improve on life.

I am ready to continue with introductory comments, but time flies when you are having fun and I would like to finish this post in the next 30 minutes if possible.

The main subject for this post is LeetCode 31 Next Permutation problem. If interested take a look at the site and decide if you wish to try it.

Implement next permutation, which rearranges numbers into the "lexicographically next greater permutation" of numbers. If such an arrangement is not possible, it must rearrange it as the lowest possible order (i.e., sorted in ascending order). The replacement must be in place and use only constant extra memory. Constraints: 1 <= nums.length <= 100 0 <= nums[i] <= 100

First, we need to make sure to understand the definition of a lexicographically ordered set of permutations is. There are different ways to generate permutations, but not all result in an ordered set. For this problem we **do not** need to **generate** the entire set of permutations for the associated number of elements, **look up** the one we are given and then **select the next one**. We could but that will be a O(n^2) process which would probably not be accepted as a solution.

What we will require is to look at the pattern, and figure out how to generate the next permutation.

I spent some time with a pen and paper. I tried some code but needed a hint. I found the following article in Wikipedia. After reading it several times and writing the associated code, I cleaned it and was able to get a solution that was accepted.

The signature for the function / method we need to generate is:

public void nextPermutation(int[] nums) { }

I will be using Java on a Windows 10 computer and the VSCode IDE to solve this problem. The simplest way is to attempt it in the IDE provided by LeetCode. Since I am using a machine at home, I will have to develop a test scaffolding. The output of several test cases follows:

1,2,3 main <<< nums: [1, 2, 3] main <<< output: [1, 3, 2] 3,2,1 main <<< nums: [3, 2, 1] main <<< output: [1, 2, 3] 1,1,5 main <<< nums: [1, 1, 5] main <<< output: [1, 5, 1] 1,5,1 main <<< nums: [1, 5, 1] main <<< output: [5, 1, 1] 4,3,2,1 main <<< nums: [4, 3, 2, 1] main <<< output: [1, 2, 3, 4] 1,2,5,8,7 main <<< nums: [1, 2, 5, 8, 7] main <<< output: [1, 2, 7, 5, 8] 15,8,4,7,6,5,3,1 main <<< nums: [15, 8, 4, 7, 6, 5, 3, 1] main <<< output: [15, 8, 5, 1, 3, 4, 6, 7] 1,2,3,4 main <<< nums: [1, 2, 3, 4] main <<< output: [1, 2, 4, 3] 1,3,2 main <<< nums: [1, 3, 2] main <<< output: [2, 1, 3] 2,3,1,3,3 main <<< nums: [2, 3, 1, 3, 3] main <<< output: [2, 3, 3, 1, 3]

Each test case takes three lines. The input line is read. The values are placed in an array and it is displayed as a sanity check. They seem to match in all the cases. The test code seems to call the function / method to generate the solution. The resulting array is then displayed.

The first three or four test cases provided by LeetCode are included. The others were generated by me or copied from the LeetCode site from a failed attempt.

The first test case represents the **first** lexicographical permutation of three numbers with the specified values. It needs to generate the second permutation. The code seems to return the correct result.

In the second test case, the **last** lexicographical permutation of three numbers with the specified values is presented. Our answer need to be the first permutation which is the input value for the first test case.

I was not able to finish this post on Sunday. The clock indicated **09:25 AM** and that is the time we need to start leaving home in order to be on our way to Trader Joe’s by **09:30 AM**. Today is early Monday morning and I am ready to finish the post.

/** * Test scafolding. * !!! NOT PART OF THE SOLUTION !!! * * @throws IOException */ public static void main(String[] args) throws IOException { // ???? test reverse function / method ???? // int[] arr = new int[]{1,2,3,4}; // System.out.println("main <<< arr: " + Arrays.toString(arr)); // reverse(arr, 3, arr.length - 1); // System.out.println("main <<< arr: " + Arrays.toString(arr)); // System.exit(-1); // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read data and populate nums[] **** int[] nums = Arrays.stream(br.readLine().trim().split(",")) .mapToInt(Integer::parseInt) .toArray(); // **** close buffered reader **** br.close(); // ???? ???? System.out.println("main <<< nums: " + Arrays.toString(nums)); // ???? ???? // int[] arr = nums.clone(); // heapPermutations(arr, arr.length, arr.length); // permute(arr, 0, arr.length - 1); // System.out.println("main <<< arr: " + Arrays.toString(arr)); // System.out.println("main <<< nums: " + Arrays.toString(nums)); // **** generate next permutation **** nextPermutation(nums); // **** display result **** System.out.println("main <<< output: " + Arrays.toString(nums)); }

Since I develop the code for the solution on my computer, I need to generate some test code that will read the input line, prepare the argument(s) for the function / method in question, invoke the function / method and display the results. Such code is **NOT PART OF THE SOLUTION!**

I really liked this problem. I knew that I needed at least two separate utility functions / methods. One is intended to reverse the contents of a set of elements in an array (e.g., 1 , 2, 3 to 3, 2, 1). The test code has been commented out. The function / method of interest is reverse() which we will look at shortly. The other function / method is swap() which will swap two locations in the specified array.

Back to the code, we read the input line and generate an int[] with the input integer values. We display the array to verify all is well so far.

The next set of lines generates permutations using different approaches. None of this function / methods produces an ordered list of permutations. At this time I will leave that as a bonus task. You can always sort the array in a lexicographical order.

We make a call to the nextPermutation() method which should generate the solution in the same nums[] array. The contents of the nums[] array is then displayed.

/** * Rearranges the numbers in nums[] into the "lexicographically next greater * permutation" of such numbers. * * The following algorithm generates the next permutation lexicographically * after a given permutation. It changes the given permutation in-place. * * Permutation * https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order * * 1) Find the largest index k such that a[k] < a[k + 1]. * If no such index exists, the permutation is the last permutation. * 2) Find the largest index l greater than k such that a[k] < a[l]. * 3) Swap the value of a[k] with that of a[l]. * 4) Reverse the sequence from a[k + 1] up to and including the final element a[n]. * * Better description for the same approach: * * 1) from right to left find adjacent values such that nums[i] < nums[i + 1] * 2) from right to left find j such that nums[j] <= nums[i] * 3) swap nums[i] with nums[j] * 4) reverse nums [i + 1 : n - 1] * * Runtime: 0 ms, faster than 100.00% of Java online submissions. * Memory Usage: 38.9 MB, less than 85.80% of Java online submissions. */ static void nextPermutation(int[] nums) { // **** sanity check **** if (nums.length <= 1) return; // **** initialization **** int n = nums.length; int i = n - 2; int j = n - 1; // **** 1) from right to left find adjacent values such that nums[i] < nums[i + 1] **** while (i >= 0 && nums[i] >= nums[i + 1]) { i--; } // **** check if not not the largest permutation **** if (i >= 0) { // **** 2) from right to left find j such that nums[j] <= nums[i] while (j > i && nums[j] <= nums[i]) j--; // **** 3) swap nums[i] with nums[j] **** swap(nums, i, j); } // **** 4) reverse nums [i + 1 : n - 1] **** reverse(nums, i + 1, n - 1); }

As I mentioned earlier, after spending some time with the problem, I needed a hint. I found the Wikipedia article that not only describes what a lexicographically next greater permutation is, but provides the steps to follow to generate one. That is condensed in the comments section of this function.

I found it very confusing. After additional coding and searching I wrote the same steps that seem to be simpler to understand. You be the judge.

We start by performing a sanity check. The initialization step follows. Please note that the simplicity is the result of multiple passes.

The first step is to traverse the array from right to left until the condition is found. We are looking for the lowest digit that we can swap. The result indicates the “next permutation”.

Note that if we cannot find such condition, we have the highest possible permutation. We need to just reverse it which will produce the lowest permutation of the set of numbers.

If we find a suitable index (i >= 0), we perform step 2. This is the other number we need to swap in the array. We swap the nums[i] with the nums[j] values and we are ready to perform the fourth step.

We need to reverse the rest of the values in order to order them in the proper sequence.

The algorithm works. Just take a few moments to try different examples with three, four and perhaps five elements. All should fall in place.

/** * Swap array values. * Time complexity: O(2) */ static void swap(int[] nums, int i, int j) { // **** sanity checks **** if (i < 0 || j < 0) return; if (i >= nums.length || j >= nums.length) return; // **** swap array values **** int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; }

This is the implementatio0n of the swap() function / method. Given that we are using it in a very controlled scenario we could have eliminated the sanity checks. In production code, you cannot second guess how the function would be called. It is much better to be safe than sorry.

/** * Reverse nums[] in the specified range. * Time complexity: O(n / 2) */ static void reverse(int[] nums, int l, int r) { // **** sanity checks **** if (i < 0 || j < 0) return; if (i >= nums.length || j >= nums.length) return; // **** initialization *** //int tmp; // **** swap end elements (left -> mid <- right) **** while (l < r) { // **** swap elements **** //tmp = nums[l]; //nums[l] = nums[r]; //nums[r] = tmp; swap(tmp, l, r); // **** update indices **** l++; r--; } }

The reverse() function / method (**OK, I am tired of writing function / method. From now on I will refer to such pieces of code as methods in this and in future posts. I fully understand the differences but such is life**) is used to reverse a range of entries in the specified array indicated by the I and j arguments.

After the sanity checks (which are not needed in this case) we initialize the tmp variable which will be used to swap two elements in the array. We should have use the swap() method instead. Using an existing method that hopefully has been fully tested is safer than reinventing the wheel. Of course, to check performance, you might try writing the three (actually four) lines of code we used in the swap() method.

We also need to love the right index to the left index to the right and the right index to the left.

As you can see this is a nice problem that ends with is solved using elegant code. I really enjoyed working on this problem. **I learn a thing or two.**

Hope you enjoyed solving this problem as much as I did. The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to help out with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a private e-mail message. I will reply as soon as possible.

Keep on reading and experimenting. It is one of the best ways to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all **6,121** subscribers to this blog!!!

Keep safe during the COVID-19 pandemic and help restart the world economy. I believe we can all see the light at the end of the tunnel.

Regards;

John

**john.canessa@gmail.com**

**As I was generating this post I checked and the blog has exceeded the 6,000 followers mark!!! Thank you all for making this happen. Hopefully it is having some type of positive impact on your learning journey.**

Yesterday or early today I received a message from HackerRank suggesting a problem. Since I had some time between a completed task for work and lunch, I decided to give it a try. The problem is ranked EASY so it should not take too much time so solve. The problem is named Halloween Party. It will seem quite appropriate after we read the description.

Alex is attending a Halloween party with his girlfriend, Silvia. At the party, Silvia spots the corner of an infinite chocolate bar (two dimensional, infinitely long in width and length). If the chocolate can be served only as 1 x 1 sized pieces and Alex can cut the chocolate bar exactly K times, what is the maximum number of chocolate pieces Alex can cut and give Silvia? Input Format: The first line contains an integer T, the number of test cases. T lines follow. Each line contains an integer K. Output Format: T lines; each line should contain an integer that denotes the maximum number of pieces that can be obtained for each test case. Constraints: o 1 <= T <= 10 o 2 <= K <= 10^7 Note: Chocolate must be served in 1 x 1 sized pieces. Alex can't relocate any of the pieces, nor can he place any piece on top of another.

The problem is very well defined. Take a look at the diagram included in the HackerRank site. We have an infinitely large chocolate bar (who does not like chocolate?). The idea is that we are given the number of cuts that we can make. Each piece of chocolate must be 1 x 1 units. We need to cut as many pieces as possible given the number of cuts we can make.

If you make no cuts you do not end up with any 1 x 1 pieces. If you make a single cut on the vertical or horizontal direction, you end with an infinitely long 1 x infinity piece. If you make a second cut on the 1 x infinity piece in order to get a 1 x 1 piece you end up with a single piece.

At this time please take a few minutes figuring out on a piece of paper how we can get the **maximum** number of 1 x 1 pieces to make some points with Silvia. Go ahead; I will wait for you …

… You are back!

The math is not too complicated. Just experiment with 2, 3, … number of cuts so you can determine mathematically what you are looking for.

If you are not new to my blog, you know that I like to solve the problems on my computers at home. HackerRank provides a test scaffolding which will be used to test our code. I will develop the solution on a Windows 10 computer using the Java programming language and the VSCode IDE.

/* * Complete the halloweenParty function below. */ static long halloweenParty(int k) { /* * Write your code here. */ }

The signature for the solution indicates that we are to write code inside the halloweenParty() function / method with has as an argument the total number of cuts we can perform.

9 0 1 2 3 4 5 6 7 8 main <<< T: 9 main <<< k: 0 main <<< pieces: 0 main <<< k: 1 main <<< pieces: 0 main <<< k: 2 main <<< pieces: 1 main <<< k: 3 main <<< pieces: 2 main <<< k: 4 main <<< pieces: 4 main <<< k: 5 main <<< pieces: 6 main <<< k: 6 main <<< pieces: 9 main <<< k: 7 main <<< pieces: 12 main <<< k: 8 main <<< pieces: 16

Let’s see if we can follow the screen capture for the test scaffolding we wrote. To be honest I did not take time to look at the code provided by HackerRank. It might be simpler and nicer than what I have. What can I say.

The first input number indicates the number of test cases we will process in this batch. The following numbers are processed one by one. Each line is a test case. The number indicates the total number of cuts we can perform on our magical chocolate bar.

Note that all the values provided by HackerRank are included in my list. I added some end cases to make sure we do not have issues with them.

Our test code seems to read and display each argument followed by the associated response which is labeled as the number of pieces we cut. The results for the provided test cases by HackerRank seem to match. Perhaps we got it right. Will find out when the code is submitted.

/** * Test scaffolding. * * @throws IOException */ public static void main(String[] args) throws IOException { // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read number of test cases **** int T = Integer.parseInt(br.readLine().trim()); // ???? ???? System.out.println("main <<< T: " + T); // **** loop once per test case **** for (int t = 0; t < T; t++) { // **** read the number of cuts **** int k = Integer.parseInt(br.readLine().trim()); // ???? ???? System.out.println("main <<< k: " + k); // **** compute and display result **** System.out.println("main <<< pieces: " + halloweenParty(k)); } // **** close buffered reader **** br.close(); }

Our test scaffolding is simple. We use a buffered reader to read each value at a time. When we enter the loop we have the total number of test cases so we only need to read the number of cuts. Once we have read and displayed the value we call the function in question and display the returned value (as pieces).

/* * Complete the halloweenParty function below. * v == vertical cuts * h == horizontal cuts */ static long halloweenParty(int k) { // **** sanity check(s) **** if (k < 2) return 0; // **** distribute the cuts (k = v + h) **** long v = k / 2; long h = k - v; // **** compute and return the number of pieces **** return v * h; }

We start by performing some sanity checks. Let’s think how many 1 x 1 pieces can we get with no cuts? The answer is 0. The same holds true if we have a single cut. When we get to 2 cuts, if we made them 1 unit from the horizontal edge and 1 unit from the vertical edge, then we have 1 piece.

We need to figure the maximum number of pieces to get with the number of cuts we have. If the number is divisible by two (i.e., 4) we could make 2 cuts in each direction for a total of 4 1 x 1 pieces. If the number is not even (i.e., 5) then we could get 2 on one direction and 3 in the other for a total of 6 pieces. With this in mind we can come up with the next two statements.

The only thing missing is to generate the number of pieces. That is computed by multiplying the number of cuts.

The code was accepted by HackerRank.

Hope you enjoyed solving this problem as much as I did. The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to help out with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a private e-mail message. I will reply as soon as possible.

Keep on reading and experimenting. It is one of the best ways to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all ** 6,008** subscribers to this blog!!!

Keep safe during the COVID-19 pandemic and help restart the world economy. I believe we can all see the light at the end of the tunnel.

Regards;

John

**john.canessa@gmail.com**

Yesterday I attended an ACM webinar “Agent-Human Collaboration and Learning for Improving Human Satisfaction” by Sarit Kraus. She is a professor of computer science at the Bar-Ilan University in Israel.

What called my attention was the concept of having agents for both the automation and the human. I can easily see how that would work in a healthcare or a disaster scenario I do not see how that could work well with autonomous cars. I will go over the slides tomorrow and see if I missed something; otherwise I will send her a message. Hopefully she will have time to respond. Will let you know my findings.

OK, now to the main topic for this post. I am not sure how many software engineers have to implement the merge sort algorithm as part of their work. That does not mean that one should not have a working idea of it. The same holds true for most sorting algorithms which are used quite often at work.

In addition to having a working idea of the algorithm, one must have access to performance data in order to select and test possible algorithms when sorting is required. Some time ago I found the Know Thy Complexities! page which has a couple tables and diagram comparing time and space complexities of different algorithms. I have the page booked marked on Chrome.

Algorithms Time Complexity Space Complexity Best Average Worst Worst Mergesort Ω(n log(n)) Θ(n log(n)) O(n log(n)) O(n)

The motivation for this post was the course Advanced Data Structures and Algorithms in Java 9 by Debasish Ray Chawdhuri on Packt. Part of the code I used to experiment with the algorithm came from his GitHub repository.

There is a good diagram and explanation of the merge sort algorithm in Wikipedia.

The Merge Sort article by GeeksforGeeks also offers several implementations of the algorithm using different programming languages.

The Merge Sort article in Wikipedia contains a nice animation of the merge sort algorithm.

If you perform a search on the web for “merge sort” you should be able to find enough material to spend a couple days reading and experimenting.

main <<< array: [38, 27, 43, 3, 9, 82, 10] mergeSort <<< l: 0 m: 3 r: 6 mergeSort <<< l: 0 m: 1 r: 3 mergeSort <<< l: 0 m: 0 r: 1 merge <<< n1: 1 n2: 1 merge <<< L: [38] merge <<< R: [27] mergeSort <<< l: 2 m: 2 r: 3 merge <<< n1: 1 n2: 1 merge <<< L: [43] merge <<< R: [3] merge <<< n1: 2 n2: 2 merge <<< L: [27, 38] merge <<< R: [3, 43] mergeSort <<< l: 4 m: 5 r: 6 mergeSort <<< l: 4 m: 4 r: 5 merge <<< n1: 1 n2: 1 merge <<< L: [9] merge <<< R: [82] merge <<< n1: 2 n2: 1 merge <<< L: [9, 82] merge <<< R: [10] merge <<< n1: 4 n2: 3 merge <<< L: [3, 27, 38, 43] merge <<< R: [9, 10, 82] main <<< sorted array: [3, 9, 10, 27, 38, 43, 82] main <<< array: [27, 9, 82, 38, 3, 43, 10] main <<< sorted array: [3, 9, 10, 27, 38, 43, 82] main <<< array: [38, 43, 10, 82, 27, 9, 3] main <<< sorted array: [3, 9, 10, 27, 38, 43, 82]

Our test scaffolding uses a single hardcoded array with seven integer elements. We use a first implementation and display some key values. You might wish to try the values used by the Wikipedia animation which could be even more beneficial to understand.

As we can see when the sort operation is over, the values in the entire array end up in ascending order.

We then shuffle the array and run it through two additional implementations. At some point I reused the input array so all passes would use the same initial order. Since we are not performing time comparisons, the order of the values before sorting should not make a difference.

/** * Test scaffolding. */ public static void main(String[] args) { // **** initial array to sort **** // Integer[] array = new Integer[]{10, 5, 2, 3, 78, 53, 3, 1, 1, 24, 1, 35,35, 2, 67, 4, 33, 30}; // Integer array[] = new Integer[]{ 12, 11, 13, 5, 6, 7 }; Integer[] array = new Integer[]{38, 27, 43, 3, 9, 82, 10, 1, 72}; // **** display array to sort **** System.out.println("main <<< array: " + Arrays.toString(array)); // **** 1) merge sort the array **** mergeSort(array, 0, array.length - 1); // **** display sorted array **** System.out.println("main <<< sorted array: " + Arrays.toString(array) + "\n"); // **** shuffle the array **** List<Integer> lst = Arrays.asList(array); Collections.shuffle(lst); array = lst.stream().toArray(Integer[]::new); // **** display array to sort **** System.out.println("main <<< array: " + Arrays.toString(array)); // **** auxiliary array **** Integer[] anotherArray = new Integer[array.length]; // **** 2) merge sort no copy **** array = mergeSortNoCopy(array, 0, array.length, anotherArray, (a, b) -> a - b); // **** display sorted array **** System.out.println("main <<< sorted array: " + Arrays.toString(array) + "\n"); // **** shuffle the array **** lst = Arrays.asList(array); Collections.shuffle(lst); array = lst.stream().toArray(Integer[]::new); // **** display array to sort **** System.out.println("main <<< array: " + Arrays.toString(array)); // **** 3) merge sort **** mergeSort(array, 0, array.length, anotherArray, (a, b) -> a - b); // **** display sorted array **** System.out.println("main <<< sorted array: " + Arrays.toString(array)); }

We start with an array of integers in no specific order. We display the array to make sure we start with an unsorted order.

We then sort the elements with the first implementation. The results are displayed. The values appear in sorted order.

The process repeats two more times with two additional implementations.

Note that each time we invoke a sort there is a digit (i.e., 1, 2 or 3). Since the code is split into different functions / methods the numbers are there to help us find the function / method in questions. Your IDE would probably find the proper implementations by just selecting the name and asking. That is the behavior of the VSCode IDE. The same holds for the Eclipse IDE and many others.

Before looking at the code for the different implementations, the idea is to split and sort the array until we end up with one digit in each set / array. We then start selecting the values and moving them to an ordered sort. After the last pass we end up with a sorted array.

This would be a good time to get a piece of paper and pen and try the algorithm. The animation and using the values of the animation in the code would also help. Go for it. I will wait…

…OK, now we can continue.

/** * MergeSort entry point (1) * Recursive call. */ static void mergeSort(Integer arr[], int l, int r) { // **** **** if (l < r) { // **** find the middle point **** int m = (l + r) / 2; // ???? ???? System.out.println("mergeSort <<< l: " + l + " m: " + m + " r: " + r); // **** sort first and second halves (recursive calls) **** mergeSort(arr, l, m); mergeSort(arr, m + 1, r); // **** merge sorted halves **** merge(arr, l, m, r); } }

We decide if we can continue to split the array. If so we find the midpoint. We then recursively sort the left side of the array followed by the right side.

After recursion returns, we merge the sorted sub arrays.

Note that the implementation makes sense based on the explanations we have read, the diagrams and animations we have looked at.

/** * Merges two subarrays of arr[] (1). * First subarray is arr[l..m] * Second subarray is arr[m + 1 ... r] */ static void merge(Integer arr[], int l, int m, int r) { // **** determine the sizes of two subarrays to be merged **** int n1 = m - l + 1; int n2 = r - m; // ???? ???? System.out.println("merge <<< n1: " + n1 + " n2: " + n2); // **** create temp arrays **** Integer L[] = new Integer[n1]; Integer R[] = new Integer[n2]; // **** copy data to the temp arrays **** for (int i = 0; i < n1; ++i) L[i] = arr[l + i]; for (int j = 0; j < n2; ++j) R[j] = arr[m + 1 + j]; // ???? ???? System.out.println("merge <<< L: " + Arrays.toString(L)); System.out.println("merge <<< R: " + Arrays.toString(R)); // **** initial indexes of first and second subarrays **** int i = 0, j = 0; // **** initial index of merged subarry array **** int k = l; // **** copy L[] and R[] elements **** while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i++]; } else { arr[k] = R[j++]; } k++; } // **** copy remaining elements of L[] (if any) **** while (i < n1) { arr[k++] = L[i++]; } // **** copy remaining elements of R[] (if any) **** while (j < n2) { arr[k++] = R[j++]; } }

This is the merge function / method. We define the indices we will use to traverse the values of interest. We put the sorted values into the arrays and copy back the resulting sorted values into the array.

/** * Merge sort no copy entry point (2). */ public static <E> E[] mergeSortNoCopy(E[] sourceArray, int start, int end, E[] tempArray, Comparator<E> comparator) { // **** **** if (start >= end - 1) { return sourceArray; } // **** initialization **** int mid = (start + end) / 2; // **** recursive calls **** E[] sortedPart1 = mergeSortNoCopy(sourceArray, start, mid, tempArray, comparator); E[] sortedPart2 = mergeSortNoCopy(sourceArray, mid, end, tempArray, comparator); // **** **** if (sortedPart2 == sortedPart1) { if (sortedPart1 == sourceArray) { merge(sortedPart1, sortedPart2, start, mid, end, tempArray, comparator); return tempArray; } else { merge(sortedPart1, sortedPart2, start, mid, end, sourceArray, comparator); return sourceArray; } } else { merge(sortedPart1, sortedPart2, start, mid, end, sortedPart2, comparator); return sortedPart2; } }

This function / method implements the second pass of the merge sort algorithm. Note that the previous implementation was restricted to Integers. This implementation supports any data type or class. This can be achieved by passing a comparator.

Also note that we are passing and additional array so we will not need to create additional arrays during the different passes of the merge implementations. That tends to improve the performance of the implementation.

/** * Merge implementation (2 & 3). */ private static <E> void merge(E[] arrayL, E[] arrayR, int start, int mid, int end, E[] targetArray, Comparator<E> comparator) { // **** **** int i = start; int j = mid; int k = start; // **** **** while (k < end) { // **** **** if (i == mid) { targetArray[k] = arrayR[j]; j++; } else if (j == end) { targetArray[k] = arrayL[i]; i++; } else if (comparator.compare(arrayL[i], arrayR[j]) > 0) { targetArray[k] = arrayR[j]; j++; } else { targetArray[k] = arrayL[i]; i++; } // **** **** k++; } }

This is the implementation of the merge step. Also note that we will reuse this code in the third implementation.

/** * Entry call that implements the MergeSort algorithm (3). */ public static <E> void mergeSort(E[] sourceArray, int start, int end, E[] tempArray, Comparator<E> comparator) { // **** end base case **** if (start >= end - 1) { return; } // **** initialization **** int mid = (start + end) / 2; // **** recursive calls **** mergeSort(sourceArray, start, mid, tempArray, comparator); mergeSort(sourceArray, mid, end, tempArray, comparator); // **** merge both arrays **** merge(sourceArray, start, mid, end, tempArray, comparator); // **** copy temp to source array **** System.arraycopy(tempArray, start, sourceArray, start, end - start); }

This represents the third implementation of the merge sort algorithm. We specify a base case followed by the recursive calls to sort the left and right sides of the array.

After the recursive calls complete we merge the resulting arrays placing the values in sorted order.

/** * Merge sort entry point (3). */ private static <E> void merge(E[] array, int start, int mid, int end, E[] targetArray, Comparator<E> comparator) { merge(array, array, start, mid, end, targetArray, comparator); }

This function / method allow us to reuse the merge function / method that we saw in the second implementation of the merge sort algorithm.

Like I said, chances are that in our workplace we might never have the need to implement the merge sort but if we do, I strongly suggest to start with proven code and make the necessary modifications. What is important is to understand the time and space complexities. Note that the worse cases should be taken into account based on the order of the data. Keep in mind that many sorting algorithms tend to perform badly when the data is close or already sorted.

One last thing, many thanks to all **5,976** subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**

Close to home, my wife and I continue to practice social distancing. On Sunday we had family members visiting. No one wore masks but we all kept at a distance from each other. Of course, we will not know if something happened for a couple weeks.

Yesterday evening I took a look at LeetCode 1249. Minimum Remove to Make Valid Parentheses. I did not have time to come up with a solution. This morning I started a little earlier so I could allot some time to finishing and posting my solution.

Given a string s of '(' , ')' and lowercase English characters. Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string. Formally, a parentheses string is valid if and only if: o It is the empty string, contains only lowercase characters, or o It can be written as AB (A concatenated with B), where A and B are valid strings, or o It can be written as (A), where A is a valid string. Constraints: o 1 <= s.length <= 10^5 o s[i] is one of '(' , ')' and lowercase English letters.

The problem is **similar** to the one in which we are asked to check if a set of parenthesis is valid or not. In this one we need to remove the minimum possible number of parenthesis to return a balanced string. It is somewhat more complicated than the similar one.

LeetCode does a good job with the requirements. They complement it with four examples.

I will solve this problem from home using a Windows 10 computer, the VSCode IDE and the Java programming language. For that reason I will need to build some test code (scaffolding) to read in the input string, pass it to the required function / method and display the results. Please note that this test code **IS NOT PART OF THE SOLUTION**.

When I am ready to test at LeetCode I will copy and paste the contents of my function / method and check if it passes the initial tests and then if it is accepted.

public String minRemoveToMakeValid(String s) { }

The signature of the function / method is as expected. Not much to add.

lee(t(c)o)de) main <<< s ==>lee(t(c)o)de)<== main <<< output ==>lee(t(c)o)de<== a)b(c)d main <<< s ==>a)b(c)d<== main <<< output ==>ab(c)d<== ))(( main <<< s ==>))((<== main <<< output ==><== (a(b(c)d) main <<< s ==>(a(b(c)d)<== main <<< output ==>a(b(c)d)<==

Our test code needs to read the input string. We display the string to make sure all is well so far. We must be making a call to the method / function of interest and displaying the result. It seems that our four tests return the expected results.

/** * Test scaffolding * * @throws IOException */ public static void main(String[] args) throws IOException { // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read input string **** String s = br.readLine().trim(); // **** close buffered reader **** br.close(); // ???? ???? System.out.println("main <<< s ==>" + s + "<=="); // **** call method of interest and display output **** System.out.println("main <<< output ==>" + minRemoveToMakeValid(s) + "<=="); }

Our test scaffolding uses a buffered reader to read in the string. The test code displays the string. The function / method of interest is called and the returned string is displayed. Not much to add here either.

/** * Method of interest. * o No close parenthesis before open parenthesis. * o Open and close parentesis must balance (+1 and -1). * Runtime complexity: O(n) * * Runtime: 8 ms, faster than 97.33% of Java online submissions. * Memory Usage: 40 MB, less than 39.11% of Java online submissions. */ static String minRemoveToMakeValid(String s) { // **** sanity check(s) **** if (s == null) return null; if (s.equals("")) return ""; // **** initialization **** StringBuilder out = new StringBuilder(); int pc = 0; char[] chArr = s.toCharArray(); // **** traverse string right to left <- **** for (int i = chArr.length - 1; i >= 0; i--) { // **** for ease of use **** char ch = chArr[i]; // **** count parenthesis **** if (ch == ')') pc++; else if (ch == '(') { // **** update count or remove parenthesis **** if (pc == 0) { // **** remove this parenthesis **** chArr[i] = 'X'; } else { // **** count this parenthesis **** pc--; } } } // **** check if parenthesis are NOT balanced **** if (pc != 0) { // **** no parenthesis counted yet **** pc = 0; // **** traverse string left to right -> **** for (int i = 0; i < chArr.length; i++) { // **** for ease of use **** char ch = chArr[i]; // **** count parenthesis **** if (ch == '(') pc++; else if (ch == ')') { // **** update count OR remove parenthesis **** if (pc == 0) { // **** remove this parenthesis **** chArr[i] = 'X'; } else { // **** count this parenthesis **** pc--; } } } } // **** build string to return **** for (char ch : chArr) { if (ch != 'X') out.append(ch); } // **** return output string **** return out.toString(); }

We perform some sanity checks. I always like to check the arguments to make sure they are what we expect them to be.

We will use a string builder to build the string that we need to return. We could have used a String but it is considerably more efficient to use a string builder. If interested in verifying this last statement, please swap the use of the string builder with strings and compare the run times.

The pc variable (parenthesis count) is used to determine if parenthesis are balanced. For each open parenthesis we must have a closing one. In our case we will **increment** the pc variable when we encounter an open parenthesis and **decrement** it when we see a close parenthesis.

The chArr[] is used for simplicity. We could extract a character from the string each time we needed one, or just initialize and populate a character array. We will also be altering the character arrays so if we use strings the performance hit will be higher.

We will be traversing the string from right to left and if needed form left to right. The reason is to take care of unbalanced open and closed parenthesis.

We enter the first loop and process each character in the chArr[] at a time. If the character is a **close** parenthesis we just update the counter. If the character is a **open** parenthesis we check if there is no previous parenthesis. This will take care of ending parenthesis. We flag the condition in the chArr[] because we need to remove this parenthesis from the returning string. If that is not the case, we just count the parenthesis and continue looping.

Note that I started moving right to left on the string. In the initial code I had the second loop before this one. I was looking to see if I could make the code more efficient by making changes in how the string builder was being populated. You can swap the loops and all should work the same.

If all parentheses are balanced, there is no need to enter the second loop.

If the parentheses are not balanced, then we need to traverse the string (character array) in reverse order to remove unneeded unbalanced parenthesis. The only difference is checking for an open or a close parenthesis first.

After we pass the two loops, we need to build a string to return. For that we use the string builder. We append all remaining parenthesis and all lower case letters. Note that we had any unbalanced parenthesis replaced by ‘X’.

We return the string representation of the string builder as the answer.

Keep on reading and experimenting. It is the best way to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all **5,959** subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**

I had scheduled a video call today at 12:00 PM CST. At least that is what I recall. This morning around 07:00 AM I was down in my home office working. At some point I checked my Gmail and I had received a message to reschedule. **Apparently I had missed the call.**

I was able to connect, apologize, and reschedule for later this the week. The new appointment showed with the proper day and time.

Later in the morning the original message at 08:30 AM CST showed up on my Google calendar. Not sure what went on. I have been using Gmail and Google calendar for years. I have not experienced a problem like this before. That said; a **different** appointment that allegedly was set for this week on a **different** day **appears to have moved** to a later time on the same day.

The main subject for this post is Vectors in Java. Most programming languages seem to have a data structure with the same name and as expected works in similar ways.

Vectors store the data in a linear fashion, but unlike arrays, they do not have a fixed size. Instead, their size can be increased as needed. To use vectors in Java, we have to import the Vector class from java.util package.

When we need to change the size of an array data structure in the middle of a program, vectors as to oppose to arrays, allow us to do so. In addition, vectors are synchronized, which gives them an advantage over array lists when dealing with multithreaded programs, because of the risks of data corruption. That said; in most (never generalize) of the problems we coven in this blog, there is typically no need to be concerned with side effects regarding multithreaded programs. Our programs /solutions tend to be single threaded.

If you are like me, I like to always hear the requirements and facts straight from the horse’s mouth. In this case, depending on your JDK version, you should get the associated vector information from Oracle.

5,9,1,11,7,2,13,1 main <<< arr: [5, 9, 1, 11, 7, 2, 13, 1] main <<< size: 0 capacity: 10 main <<< v1: [5, 9, 1, 11, 7, 2, 13, 1] main <<< size: 8 capacity: 10 main <<< v1: [] main <<< size: 0 capacity: 10 main <<< v1: [5, 9, 1, 11, 7, 2, 13, 1] main <<< size: 8 capacity: 10 main <<< v1: [5, 9, 17, 1, 11, 7, 2, 13, 1] main <<< size: 9 capacity: 10 main <<< v1: [5, 9, 17, 1, 11, 7, 2, 13, 1, 19, 23] main <<< size: 11 capacity: 20 main <<< v1: [5, 9, 17, 1, 11, 7, 2, 13, 1, 19, 23] main <<< removed: e: 5 main <<< removed: e: 17 main <<< removed: e: 11 main <<< removed: e: 2 main <<< removed: e: 1 main <<< removed: e: 23 main <<< EXCEPTION e: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 6 i: 6 main <<< v1: [9, 1, 7, 13, 19] main <<< size: 5 capacity: 20 main <<< v1: [9, 1, 7, 13, 19, null, null, null, null, null] main <<< size: 10 capacity: 20 main <<< v1: [9, 1, 7, 13, 19] main <<< size: 5 capacity: 20 main <<< v1: [9, 1, 7, 13, 19] main <<< size: 5 capacity: 5 main <<< v1: [1, 5, 7, 9, 13, 19] main <<< size: 6 capacity: 10

Since we do not have a problem at hand to solve, the test scaffolding is just a set of operations in no specific order. For it to make sense we need to look at the source code.

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Collections; import java.util.Vector; import java.util.stream.Collectors; /** * */ public class VectorsInJava { /** * Test scaffolding. */ public static void main(String[] args) throws IOException { // **** initialization **** int[] arr = null; // **** open a buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** create and read arr[] values used to populate a vector **** arr = Arrays.stream(br.readLine().trim().split(",")) .mapToInt(Integer::parseInt). toArray(); // **** close the buffered reader **** br.close(); // **** display the contents of the array **** System.out.println("main <<< arr: " + Arrays.toString(arr)); // **** create and populate a vector **** Vector<Integer> v1 = new Vector<Integer>(); // **** display size and capacity **** System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** populate vector **** for(int a : arr) v1.add(a); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** clear vector **** v1.clear(); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** populate vector with arr[] **** v1.addAll(Arrays.stream(arr).boxed().collect(Collectors.toList())); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** insert value at specified position **** v1.add(2, 17); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** add a couple more values **** v1.add(19); v1.add(23); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** traverse the vector **** System.out.print("main <<< v1: ["); for (int i = 0; i < v1.size(); i++) { System.out.print(v1.get(i)); if (i < v1.size() - 1) System.out.print(", "); else System.out.print("]"); } System.out.println(); // **** remove some entries from the vector **** for (int i = 0; i < 10 && !v1.isEmpty(); i++) { // **** remove entry i from vector **** try { int e = v1.remove(i); System.out.println("main <<< removed: e: " + e); } catch (Exception e) { System.out.println("main <<< EXCEPTION e: " + e.toString() + " i: " + i); break; } } // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** double the size of the vector (will add null elements) **** v1.setSize(v1.size() * 2); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** remove all null elements from the vector **** while (v1.contains(null)) v1.remove(null); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** trim capacity to current size **** v1.trimToSize(); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); // **** add element to the vector **** v1.add(5); // **** sort the vector contents **** Collections.sort(v1); // **** display vector **** System.out.println("main <<< v1: " + v1.toString()); System.out.println("main <<< size: " + v1.size() + " capacity: " + v1.capacity()); } }

We start as usual importing some libraries. Please note, that I never import libraries in advanced. I have my IDE (in this case VSCode) to suggest the set of libraries that I might use when I specify an operation in a statement. You could always copy and paste the imports when you start writing some code.

The next steps are associated with reading an input line from the console. The data is use to populate an array. In this example we could have just declared the array with the same values. At the time I did not choose to do so because I was planning on reading different data for different operations. After my fiasco with the call I missed earlier today, I decided to read data once and experiment with it. Note that if this example were production code, I would have made the necessary changes. It seems that using a stream would be like, using a cannon to kill a mosquito.

We read and display the contents of our arr[].

Next we create an empty Integer vector. We could have specified a collection to load the vector and some behaviors which you can read in the Class Vector<E> page.

We display the size and capacity of our vector.

We are ready to load the vector with the values in the arr[]. We do so by entering a loop and adding the elements one by one. The contents are then displayed. Note that we read 8 items and the capacity is 10. We can add a couple more elements and the capacity will remain at 10. As soon as we add the 11^{th} element, the capacity will increase by 10 to a total of 20. We will see that shortly.

We decided to clear all the elements from our vector. This is confirmed by the following two statements.

In the next statement we load the vector with a list generated from the arr[]. This is just showing us that we may populate a vector with the contents of a list.

We will now **add two more elements** to our vector and display the contents. Note that the **size** and **capacity** are both 10.

We add a new element at a specified position and two more at the end of the vector. At some point the capacity of the vector increases to 20. This was automatically accomplished by the vector class. If you are wondering if we can shrink the capacity, the answer is yes and will see how shortly.

We now enter a loop and display the contents of the vector. We are doing so to demonstrate how individual elements in a vector are accessed.

The next loop is used to demonstrate that we can remove elements from the vector. We decided to remove them by location so at some point our loop throws an exception. Note that we can always remove an element at the start or end of a vector in a loop until the vectors is empty.

We display the vector to get an idea of which elements remain and their positions in the array. Note that the size if now 5 but the capacity remains at 20.

We can double the size from 5 to 10. As you can see we have added **5 null** entries in the vector. The capacity remains at 20. We then remove the null entries and the size goes down to 5 and the capacity remains at 20.

We now trim the vector to its size. As you can see the size of 5 now matches the capacity of 5.

Finally we add element 5 to our vector. The size goes up to 6 but the capacity went up to 10. This is the default behavior of the capacity. We could have specified a different capacity increment when we declared the vector, but we did not.

As you can see there are many more ways we can experiment with vectors in order to better get to know their behavior. Becoming familiar with a class / library will help us solve future problems applying the best possible data structure for the problem at hand.

Keep on reading and experimenting. It is the best way to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all 5,938 subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**

It seems that in the EU the GDPR has had little for user privacy. The article contains a table containing a list of countries in which homosexuality, which is a label that could be assigned to your account, in which homosexuality is a crime that could be punished by the death penalty. Potentially that could be detrimental to about 1% – 3% of Facebook users.

If you have any interest on this subject, I would suggest for you to read the article and reach your own conclusions. Keep in mind that no one forces you to have an account and use the Facebook platform. Since there are millions of users worldwide, the platform must provide features that are of interest to so many people. I believe there is no charge to use Facebook. They need ways to generate revenue to continue to provide their services.

I am not sure when I registered for HackerEarth. That said, late last week I received the following message via Gmail:

John, we value your opinion I am Sachin Gupta, the founder of HackerEarth. I noticed that you recently joined HackerEarth but haven't spent much time on our platform. I would love to understand what went wrong with your experience and how we can make your journey on HackerEarth more productive. I'd also like to share three things you can do to get started with coding on HackerEarth: o Solve coding problems to prepare for interviews o Competing with fellow developers and earning bragging rights o Participating in hackathons to solve real-world problems We'd love to hear your feedback. To share your thoughts simply reply to this email. Happy Coding! Cheers Sachin

I thought it was a nice touch from HackerRank so I spent some time researching the company on-line and solved my first problem. The main subject of this post is based on the Can you solve it? problem.

I am a firm believer on the idiom “don’t judge a book by its cover” so I will **reply in private** to the message I received and in the future will try **solving a few problems** to get a better feeling about what the site has to offer.

Yesterday I spent some time browsing the HackerEarth web site. At some point I selected Can you solve it? and gave it a try.

The problems are presented in a similar style like in other similar web sites. The requirements for this problem follow:

Raman loves Mathematics a lot. One day his maths teacher gave him an interesting problem. He was given an array 'A' consisting of 'n' integers, he was needed to find the maximum value of the following expression: |Ai - Aj| + |i - j| where, 0 <= i, j < n and Ai, Aj are the Array elements. Input: o First line of input contains an integer T denoting number of test cases. o Each test case contains two lines, first line contains integer n where n is the number of elements in array Second line contains n space separated integers Ai. Output: Print the maximum value of the above give expression, for each test case separated in a new line. Constraints: o 1 <= T <= 100 o 1 <= n <= 105 o 0 <= Ai <= 105 Note: Use Fast I/O (scanf/printf or any other ways) to handle large test files.

We are given an array on integers in no specific order which may or may not contain duplicates.

The idea is to return the maximum value for the expression which represents the absolute value of the difference of two array elements added to the difference of their respective indices. I do not believe you should rearrange (i.e., sort) the array.

4 3 1 1 1 4 1 2 3 1 1 69 2 11 13 main <<< result: 2 main <<< result: 2 main <<< result: 4 main <<< result: 4 main <<< result: 0 main <<< result: 0 main <<< result: 3 main <<< result: 3

We are given a number of test cases. The site provides the first two cases. I added the rest.

Each test case is specified by two lines. The first line contains the number of elements in the array. The second line the actual integers.

I founded interesting that HackerEarth did not provide the signature for the function / method that we are required to solve. In addition the HackerEarth IDE provided part of a test scaffolding. I disregarded the test code and wrote my own on my computer. I did copy and pasted it when I was ready to run tests and check if the solution was good enough.

Personally I like **complete** test scaffoldings and the **signature** of the class / function(s) / method(s) one has to develop. As you know some people like chocolate while others do not.

Note that I display two results per test cases. The reason for this is that I have two versions of the solution. The first seems to work but it represents the brute force approach. It was not granted full credit. The second value, which seems to match the first on these test cases, is an optimized solution (labeled as “tricky”) which as we will see, not too intuitive and much harder to come up with.

As you might already know, I like to solve problems using my computer and if possible the tools of my choice. This is how most, never generalize, software engineers work. I will use the Java language on a Windows 10 computer and the VSCode IDE. I have access and use for work other programming languages, computers and IDEs, but by choice I am mostly sticking to Java, Windows and VSCode. You are free to use whatever you like which includes the HackerEarth IDE.

One simple note, submit a single solution and **do not add text to the answer** (i.e., “main <<< “) as I have shown in the examples.

/** * Test scaffolding * * @throws IOException */ public static void main(String[] args) throws IOException { // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read number of test cases **** int N = Integer.parseInt(br.readLine().trim()); // **** loop once per test case **** for (int i = 0; i < N; i++) { // **** skip array length **** br.readLine(); // **** create and populate arr[] **** int[] arr = Arrays.stream(br.readLine().trim().split(" ")) .mapToInt(Integer::parseInt) .toArray(); // **** compute and display result (two approaches) **** System.out.println("main <<< result: " + maxValue1(arr, arr.length)); System.out.println("main <<< result: " + maxValue(arr, arr.length)); } // **** close buffered reader **** br.close(); }

This is my test scaffolding. Open a buffered reader, read the number of test cases and loop through them.

For each test case, read (skip) the number of elements in the array, read the elements, call the function / method you are developing and display the returned result.

After you are done with all test cases, it is a good idea to close the buffered reader. Since this is not production code, you might not have to close it.

Note that I skipped the number of elements in the array. I was not going to pass the number of elements because I could have just obtained the length inside the called function / method. I just passed it (but not read it) to see if that would save some processing time in the actual function / method. You never know what minor change might affect your score.

/** * Find the maximum value of the following expression: * |arr[i] - arr[j]| + |[i -j]| * * First pass (searching for inspiration OR brute force). * Execution time: O(n^2) */ static int maxValue1(int[] arr, int n) { // **** sanity checks **** if (arr == null || n == 1) return 0; // **** initialization **** int maxVal = -1; // **** traverse arr[] with first element - O(n) **** for (int i = 0; i < n - 1; i++) { // **** traverse arr[] with second element - O(n) **** for (int j = i + 1; j < n; j++) maxVal = Math.max(maxVal, Math.abs(arr[i] - arr[j]) + Math.abs(i - j)); } // **** return max val **** return maxVal; }

This is the brute force approach. We perform sanity checks and initialization.

We then traverse the array in two nested loops with O(n ^ 2) execution time.

We compute the value and keep a running maximum value. When done we return the maximum value.

Short and simple, but as expected not good enough!

I spent some time looking for a pattern. I did not come with something simple. The HackerEarth site did not provide a set of hints. In practice, you will always be able to get hints / comments / suggestions from other coworkers and if you are in an interview, the interviewer should provide suggestions.

/** * Find the maximum value of the following expression: * |arr[i] - arr[j]| + |[i -j]| * * Second pass. * * Inspiration from: * https://www.geeksforgeeks.org/maximum-value-arri-arrj-j/ * * Execution time: O(n) */ static int maxValue(int[] arr, int n) { // **** sanity checks **** if (arr == null || n == 1) return 0; // **** initialization **** int[] arrA = new int[arr.length]; int[] arrB = new int[arr.length]; // **** populate arrA[] and arrB[] - O(n)**** for (int i = 0; i < n; i++) { arrA[i] = arr[i] + i; arrB[i] = arr[i] - i; } // **** for starters **** int minA = arrA[0]; int maxA = arrB[0]; // **** find max and min in arrA[] - O(n) **** for (int i = 1; i < n; i++) { // **** update maxA (if needed) **** if (arrA[i] > maxA) maxA = arrA[i]; // **** update minA (if needed) **** if (arrA[i] < minA) minA = arrA[i]; } // **** determine difference **** int diff1 = (maxA - minA); // **** for starters **** int minB = arrB[0]; int maxB = arrB[0]; // **** find max and min in arrB[] - O(n) **** for (int i = 1; i < n; i++) { // **** update maxB (if needed) **** if (arrB[i] > maxB) maxB = arrB[i]; // **** update minB (if needed) **** if (arrB[i] < minB) minB = arrB[i]; } // **** determine difference **** int diff2 = (maxB - minB); // **** return answer **** return Math.max(diff1, diff2); }

In the comments section of the function / method I wrote the link to the site I found to get inspiration / hint. What I typically do is start reading and or looking at a code example, until I can proceed. It is better not to read the entire solution or copy and paste the code for it. If you do so you will not learn much from such approach.

The solution is based on an observation and associated implementation. Since this problem is based on a mathematical expression it is simpler to read the description in the specified web site.

In a nutshell we need to generate two arrays which are associated with the observation. Once we have the arrays **populated** we need to compute the **max** and **min** values in each of the two arrays. Note that for simplicity (and efficiency) we compute two differences. When all is set and done the result is the max value of the two differences.

I suggest adding a few print statements, and watch how the solution emerges. In my opinion, this is a tricky problem and takes time to come up with a rather simple implementation. In average a problem under pressure should be solved in about 30 minutes. It took me more than that.

Keep on reading and experimenting. It is the best way to learn, become proficient, refresh your knowledge and enhance your developer toolset.

One last thing, many thanks to all **5,905** subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**

For lunch my wife prepared a Chinese meal with products from Trader Joe’s. It was quite good taking into consideration that it came from a super market. It took my wife about 30 minutes to prepare lunch from start to finish.

I was looking for a specific problem on LeetCode but could not find it. Perhaps the name has been changed. I did find Design Tic-Tac-Toe. I had to give it a try.

Assume the following rules are for the tic-tac-toe game on an n x n board between two players: o A move is guaranteed to be valid and is placed on an empty block. o Once a winning condition is reached, no more moves are allowed. o A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game. Implement the TicTacToe class: o TicTacToe(int n) Initializes the object the size of the board n. o int move(int row, int col, int player) Indicates that player with id player plays at the cell (row, col) of the board. The move is guaranteed to be a valid move. Follow up: Could you do better than O(n2) per move() operation? Constraints: o 2 <= n <= 100 o player is 1 or 2. o 1 <= row, col <= n o (row, col) are unique for each different call to move. o At most n2 calls will be made to move.

The rules are simple and match the ones for the tic-tac-toe we all used to play growing up. Our task is limited to declare variables for the class, generate the constructor to initialize the variables and accept the moves made by the two players. At some point we need to call a winner.

The test scaffolding will make sure that the players make one call at a time and they alternate. Also it seems that they will not attempt to fill a spot already used by the opponent.

The requirements look straight forward.

class TicTacToe { /** Initialize your data structure here. */ public TicTacToe(int n) { } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { } } /** * Your TicTacToe object will be instantiated and called as such: * TicTacToe obj = new TicTacToe(n); * int param_1 = obj.move(row,col,player); */

The signature for the TicTacToe class is provided. We need to fill in the **constructor** and the **move** methods.

LeetCode also provides how the TicTacToe class will be invoked and used.

I like to develop the solution in one of my machines. We will have to generate a test scaffolding to mimic what LeetCode provides. I will be using the Java programming language and the VSCode IDE running on a Windows 10 machine. After feeling confident with a solution, I will have to copy and paste the code into the LeetCode IDE and submit it for evaluation.

3 0, 0, 1 0, 2, 2 2, 2, 1 1, 1, 2 2, 0, 1 1, 0, 2 2, 1, 1 main <<< board: [1, 0, 2] [2, 2, 0] [1, 1, 1] main <<< player: 1 winner winner chicken dinner !!! 3 0, 0, 1 1, 1, 2 1, 0, 1 1, 2, 2 2, 0, 1 main <<< board: [1, 0, 0] [1, 2, 2] [1, 0, 0] main <<< player: 1 winner winner chicken dinner !!! 3 0, 0, 1 0, 2, 2 1, 1, 1 2, 0, 2 2, 2, 1 main <<< board: [1, 0, 2] [0, 1, 0] [2, 0, 1] main <<< player: 1 winner winner chicken dinner !!! 3 0, 2, 1 0, 0, 2 1, 1, 1 1, 0, 2 2, 0, 1 main <<< board: [2, 0, 1] [2, 1, 0] [1, 0, 0]

It seems that LeetCode provides one example. That is the first test we use.

The tests start with the side of the board we will use for the game. Our test code needs to read the dimension for the board. The boards are square. In this first case our board will be 3×9 with 9 cells.

Following are a set of lines. Each line contains information for a single move. The **first** integer represents the row for the move. The **second** value represents the column on the board for the move. The **third** and last argument is the player number. We have two players. The first is player 1 and the second player 2.

The idea is that our test program will process a move and will determine if the move generates a winner. This will become clear when we see the code for the test scaffolding.

At some point in the game, a winner may appear. We could check if there is a tie, but implementing such condition is not required.

If you follow the games with a piece of paper, you can determine that at some point one of the players wins the game. Note that the display of the board is an artifact of our test code. We are not required to display the board as part of the solution.

In addition, when a game ends due to a winner, the test program displays a message. That is not part of the solution.

As you can verify with a piece of paper, we have to determine is a game is won by filing a row, a column or one of the two diagonals. A test for each condition is executed to assure all is well.

/** * Test scaffolding * * @throws IOException */ public static void main(String[] args) throws IOException { // **** initialization **** int winner = 0; TicTacToe obj = null; // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // ***** loop until there is a winner **** while(winner == 0) { // **** read next input line **** String[] strArr = br.readLine().trim().split(", "); // **** initialize or move **** if (strArr.length == 1) { obj = new TicTacToe(Integer.parseInt(strArr[0])); } else { // **** parse the arguments for the move **** int r = Integer.parseInt(strArr[0]); int c = Integer.parseInt(strArr[1]); int p = Integer.parseInt(strArr[2]); // **** player makes move **** winner = obj.move(r, c, p); // **** signal winner (if needed) **** if (winner != 0) { System.out.println("main <<< board:"); System.out.println(obj.toString()); System.out.println("main <<< player: " + p + " winner winner chicken dinner !!!"); } } } // **** close the buffered reader **** br.close(); }

We start by performing initializations. We then open a buffered reader that will be used to read when to initialize the game and then read the arguments for the moves of the two players.

We then enter a loop in which we exit when a winner is found. A winner is determined by the number of the player winning the game.

We read the next line. It can be a game initialization or a move. LeetCode will start all games with an initialization. From there on we will be presented by moves from the opposing players.

When we receive data for a move, we parse the row, column and player. We then make a call to the move method which returns 0, 1 or 2 depending on the result of the move. A 0 means **no winner** yet, a 1 indicates that **player 1 won** and 2 that **player 2 is the winner**.

Our test software detects if a player won the game and displays a message. The loops exists and we close the buffered reader.

/** * Design Tic-Tac-Toe * https://leetcode.com/problems/design-tic-tac-toe/ * * Runtime: 3 ms, faster than 99.96% of Java online submissions. * Memory Usage: 42.1 MB, less than 48.10% of Java online submissions. */ public class TicTacToe { // **** class members **** public int n = 0; public int[][] board = null; /** * Initialize your data structure here. */ public TicTacToe(int n) { this.n = n; this.board = new int[n][n]; } ::: ::: :::: }

This is the TicTacToe class. The class shows the members and the constructor. The rest of the code is not displayed. The class members and the constructor are part of the solution.

Note that in the comments section we have information about our solution. I guess we did well on our first and only submission.

/** * Player {player} makes a move at ({row}, {col}). * @param row The row of the board. * @param col The column of the board. * @param player The player, can be either 1 or 2. * @return The current winning condition, can be either: * 0: No one wins. * 1: Player 1 wins. * 2: Player 2 wins. */ public int move(int row, int col, int player) { // **** initialization **** int winner = 0; // **** flag move on board **** board[row][col] = player; // **** check if we have a winner **** winner = haveWinner(row, col, player); // **** return winner **** return winner; }

The move method sets the winner variable. We then flag the space on the board for the move. We check if we have a winner and return the updated variable. We could have eliminated the winner variable and have returned the result of the haveWinner auxiliary method returned directly. You could make that change and reduce a fraction of the time from the game.

/** * Determine if we have a winner. * Execution time: O(4n) */ private int haveWinner(int row, int col, int player) { // **** initialization **** int winner = player; // **** check row O(n) **** for (int c = 0; c < this.n; c++) { if (board[row] != player) { winner = 0; break; } } // **** check if we have a winner **** if (winner == player) return winner; // **** check column O(n) **** winner = player; for (int r = 0; r < this.n; r++) { if (this.board[r][col] != player) { winner = 0; break; } } // **** check if we have a winner **** if (winner == player) return winner; // **** check first diagonal O(n) **** winner = player; for (int d = 0; d < this.n; d++) { if (this.board[d][d] != player) { winner = 0; break; } } // **** check if we have a winner **** if (winner == player) return winner; // **** check second diagonal O(n) **** winner = player; for (int d = n - 1; d >= 0; d--) { if (this.board[d][n - d - 1] != player) { winner = 0; break; } } // **** **** return winner; }

This auxiliary method checks if a row, column, or one of the two diagonals contains the player number in all the cells. If it does, we return the player number indicating this is the winner for the game. Like I stated earlier, this is the first and only pass of the code. Perhaps we could optimize further this method in order to eliminate some of the checks under some conditions. That could shave another fraction of time from the game.

**One last thing, many thanks to all 5,866 subscribers to this blog!!!**

Regards;

John

**john.canessa@gmail.com**

I started to read an article regarding Facebook on the last issue of Communications of the Association for Computer Machinery. The article Does Facebook use sensitive data for advertising purposes? called my attention. I have not finished reading the article. I will make some comments when done.

Yesterday evening, I decided to tackle the coding practice problem Balanced Split by Facebook.

The problem has an example and two test cases. Due to this fact I might have missed something. If you encounter an issue I would appreciate if you could please send me a test case illustrating the problem.

I could have solved this problem on-line using the Facebook IDE. I decided to solve it on **my computer** using the VSCode IDE and the Java language. I had to generate a test scaffolding to run tests. That said; I could have copied, pasted and executed the code on-line, but I like to have all the tools and code on my machine so I can address issues or perform further exploration without having to locate a page that could have been dropped.

Given an array of integers (which may include repeated integers), determine if there's a way to split the array into two subsequences A and B such that the sum of the integers in both arrays is the same, and all of the integers in A are strictly smaller than all of the integers in B. Note: Strictly smaller denotes that every integer in A must be less than, and not equal to, every integer in B. Input: All integers in array are in the range [0, 1,000,000,000]. Output: Return true if such a split is possible, and false otherwise.

We are given a set of integers. Some may repeat. The numbers are in no particular order. That said; we need to determine if we could split the integers into two groups that add up to the same value. But wait, there is more. The integers in the set A must be **strictly smaller** than the ones in set B.

Note that I was not able to determine by reading the requirements, the **minimum number of integers** we could be provided.

bool balancedSplitExists(int[] arr) { }

The signature for the function / method we need to develop is simple. Note that it does not comply with Java. Java does not have a **bool** data type or class. That said; Java is a supported language by the Facebook IDE.

1, 5, 7, 1 main <<< strArr: [1, 5, 7, 1] main <<< arr: [1, 5, 7, 1] main <<< output: true main <<< output: true main <<< output: true 12, 7, 6, 7, 6 main <<< strArr: [12, 7, 6, 7, 6] main <<< arr: [12, 7, 6, 7, 6] main <<< output: false main <<< output: false main <<< output: false 12, 7, 6, 7, 6 main <<< strArr: [12, 7, 6, 7, 6] main <<< arr: [12, 7, 6, 7, 6] main <<< output: false main <<< output: false main <<< output: false 3, 6, 3, 4, 4 main <<< strArr: [3, 6, 3, 4, 4] main <<< arr: [3, 6, 3, 4, 4] main <<< output: false main <<< output: false main <<< output: false 0 main <<< strArr: [0] main <<< arr: [0] main <<< output: false main <<< output: false balancedSplitExists2 <<< EXCEPTION e: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 1 1 main <<< strArr: [1] main <<< arr: [1] main <<< output: false main <<< output: false main <<< output: false 1, 2 main <<< strArr: [1, 2] main <<< arr: [1, 2] main <<< output: false main <<< output: false main <<< output: false 0, 0 main <<< strArr: [0, 0] main <<< arr: [0, 0] main <<< output: false main <<< output: false balancedSplitExists2 <<< EXCEPTION e: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 2 0, 1 main <<< strArr: [0, 1] main <<< arr: [0, 1] main <<< output: false main <<< output: false main <<< output: false 1, 1 main <<< strArr: [1, 1] main <<< arr: [1, 1] main <<< output: false main <<< output: false main <<< output: false 2 main <<< strArr: [2] main <<< arr: [2] main <<< output: false main <<< output: false main <<< output: false 20, 2 main <<< strArr: [20, 2] main <<< arr: [20, 2] main <<< output: false main <<< output: false main <<< output: false 5, 7, 20, 12, 5, 7, 6, 14, 5, 5, 6 main <<< strArr: [5, 7, 20, 12, 5, 7, 6, 14, 5, 5, 6] main <<< arr: [5, 7, 20, 12, 5, 7, 6, 14, 5, 5, 6] main <<< output: true main <<< output: true main <<< output: true 5, 7, 20, 12, 5, 7, 6, 7, 14, 5, 5, 6 main <<< strArr: [5, 7, 20, 12, 5, 7, 6, 7, 14, 5, 5, 6] main <<< arr: [5, 7, 20, 12, 5, 7, 6, 7, 14, 5, 5, 6] main <<< output: false main <<< output: false main <<< output: false 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 main <<< strArr: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] main <<< arr: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] main <<< output: false main <<< output: false main <<< output: false

Facebook provides two examples. Two additional examples are found in the unit test section. I created several test cases to address possible end conditions regarding the number of integers in the set. Some came from a site which I will mention later on.

It seems that we are provided with a set of integer values. Our test code seems to be able to read the integers and put them into a String[] array. The contents of the String[] are then displayed. All seems to be well so far.

The test code seems to generate and display an int[] using the values collected in the String[] array. The values appear to match.

The three next lines seem to invoke a version of our solution and display the results. Most of them match. We will get additional insights as we look at the different implementations.

/** * Test scaffolding * * @throws IOException */ public static void main(String[] args) throws IOException { // **** open buffered reader **** BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // **** read String[] array **** String[] strArr = br.readLine().trim().split(", "); // **** close buffered reader **** br.close(); // ???? ???? System.out.println("main <<< strArr: " + Arrays.toString(strArr)); // **** create and populate int[] (if needed) **** int[] arr = {}; if (!strArr[0].equals("")) { arr = new int[strArr.length]; for (int i = 0; i < strArr.length; i++) { if (strArr[i].equals("")) continue; arr[i] = Integer.parseInt(strArr[i]); } } // ???? ???? System.out.println("main <<< arr: " + Arrays.toString(arr)); // **** generate and display result **** System.out.println("main <<< output: " + balancedSplitExists(arr)); // **** generate and display result **** System.out.println("main <<< output: " + balancedSplitExists1(arr)); // **** generate and display result **** System.out.println("main <<< output: " + balancedSplitExists2(arr)); }

Our test scaffolding does what we implied earlier in this post. Note that the generation of the int[] array from the data in the String[] is somewhat convoluted when compared to the test code we have in other posts. The reason for it is to be able to generate int[] arrays in which the int[] is null, contains 0, 1, 2 or more elements.

We make a call to three different implementations. The first two seem to always work. The third one seems it might have an issue.

/** * Balanced split function. * Time complexity: O(n) */ static boolean balancedSplitExists(int[] arr) { // **** sanity check(s) **** if (arr == null || arr.length <= 2) return false; // **** initialization **** int i = -1; int j = arr.length; int lastA = Integer.MIN_VALUE; int lastB = Integer.MAX_VALUE; int sumA = 0; int sumB = 0; // **** sort the array O(n log(n) **** Arrays.sort(arr); // **** select numbers from outside to inside O(n) **** while (i + 1 < j && lastA != lastB) { // **** increment sumA or sumB **** if (sumA > sumB) { sumB += arr[--j]; lastB = arr[j]; } else if (sumA < sumB) { sumA += arr[++i]; lastA = arr[i]; } else { sumA += arr[++i]; lastA = arr[i]; } } // **** **** return (sumA == sumB && lastA != lastB); }

This was my first pass at the problem. The idea is to sort the array. Once it is sorted we traverse the array attempting to maintain the requirements for set A and B. When done we return a boolean indicating if the final tally for both sets adds to the same value, and because the values were sorted, that the last values processed in the sets are or are not equal.

/** * Balanced split function. * Time complexity: */ static boolean balancedSplitExists1(int[] arr) { // **** sanity check(s) **** if (arr == null || arr.length <= 2) return false; // **** initialization **** int sumA = 0; int sumB = 0; int i = 0; // **** compute sumA O(n) **** for (i = 0; i < arr.length; i++) sumA += arr[i]; // **** sort the array O(n log(n) **** Arrays.sort(arr); // **** decrement sumA while incrementing sumB O(n) **** for (i = arr.length - 1; sumA > sumB; i--) { sumA -= arr[i]; sumB += arr[i]; } // **** **** return (sumA == sumB && arr[i] != arr[i + 1]); }

This is a simpler to understand implementation. We start by performing the same set of sanity checks as we did in the previous implementation. In this case we will include in the sumA all the integer values. We then sort the array. We could have changed the order of these two statements achieving the same results.

In the final loop we start moving values from set A to set B. At some point the sums will not meet the condition in the for() loop.

After we exit the loop we check if the **sums match** and that the **last values in each set are different** (the values are sorted).

Note that both implementations are similar.

Since I wanted to find more rigorous tests to verify our solutions, I found a solution on-line. The solution was **not written in Java**. I decided to make a port because the associated test cases appear to be missing to test some conditions.

Please note that I might have induced problems when porting such code. If you find an issue please let me know.

/** * https://leetcode.com/discuss/interview-question/718692/facebook-training-balanced-split * * This implementation was ported to Java. * It seems it MIGHT have an issue :o( */ static boolean balancedSplitExists2(int[] arr) { // **** initialization **** int leftSum = 0; int rightSum = 0; // **** sort the array O(n log(n) **** Arrays.sort(arr); // **** **** for (int i = 0; i < arr.length; i++) leftSum += arr[i]; // **** **** for (int i = arr.length - 1; i >= 0; i--) { // **** **** leftSum -= arr[i]; rightSum += arr[i]; // **** **** if (leftSum == rightSum) { try { if (arr[i - 1] < arr[i]) return true; } catch (Exception e) { System.out.println("balancedSplitExists2 <<< EXCEPTION e: " + e.toString()); System.exit(-1); } } } // **** **** return false; }

The function performs initialization steps. It sorts the array. It uses an array to compute the sum of all integers from left to right. This is similar to the second approach.

In the final loop it transfers values from the left to the right sum. It then checks if the sums match. If they do, a check is made to see if the last integers in the sets are different. That causes the function to throw an exception.

If we do not run into end conditions, which could have been addressed by performing some sanity checks, the results would match the other two methods.

One last thing, many thanks to all **5,854** subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**

As I mentioned in a previous post, I am watching the video Advanced Data Structures and Algorithms in Java 9 by Debasish Ray Chawdhuri produced by Packt and published by O’Reilly. That was a mouthful. I just felt to refresh my understanding on a few algorithms.

Like most software engineers, once upon a time while in school, I studied and had to implement the algorithm for a couple classes. Since then, when at work, I tend to use sorting implementations that come in libraries. That said, if there is a performance issue, or the need to enhance an algorithm, they it is justifiable to implement your own version.

To be honest with you, I have done and do a lot of development work using C / C++ and I have used the **quicksort** implementation that comes in standard libraries. In specific I have used the function **qsort** that comes standard in the **cstdlib** of C and C++ in multiple projects and products. I have yet not encountered a situation in which I had to implement a faster implementation of such algorithm.

That said; it is very useful to understand how sorting algorithms are implemented and pay attention at the **time and space complexity** of the algorithms when you need to perform an **educated selection** in a software development project.

:::: :::: :::: // **** sort the array of full paths **** qsort( *sortedArray, countOfFiles, lengthOfEntry, strcmp); :::: :::: ::::

This code snippet is one of several in a storage server product that runs in the cloud.

main <<< arr.length: 19 main <<< arr: [10, 5, 2, 3, 78, 53, 3, 1, 1, 24, 1, 35, 35, 2, 67, 4, 33, 30, 13] quicksort <<< count: 99 main <<< arr: [1, 1, 1, 2, 2, 3, 3, 4, 5, 10, 13, 24, 30, 33, 35, 35, 53, 67, 78]

I will show a single example running the Java implementation of the algorithm on a Windows 10 machine which I developed using the VSCode IDE.

The content of the input array that provides the integers we will be sorting has been **hardcoded**. I could have added a mechanism to read the values from the console and perhaps make a copy in the file system that we could reuse. As we will see shortly, in this post, we want to run the **same** data set with different options to better understand what is going with the algorithm and offer some optimizations.

Our test scaffolding displays the length of the Integer[] followed by the actual contents of the arr[]. In this case we seem to have 19 integers and they are presented in no specific order.

We then ran our quicksort algorithm. The algorithm seems to display a count. We should be counting some operation which hopefully will indicate how the algorithm is performing. Finally we display the contents of the sorted array. The value 99 should be used for comparison purposes between passes only. In our case we are interested how the algorithm performs when the **same data** is ordered in different ways.

/** * Test scafolding */ public static void main(String[] args) { // **** array to sort **** Integer[] arr = new Integer[] {10, 5, 2, 3, 78, 53, 3, 1, 1, 24, 1, 35, 35, 2, 67, 4, 33, 30, 13}; // ???? array info ???? System.out.println("main <<< arr.length: " + arr.length); System.out.println("main <<< arr: " + Arrays.toString(arr)); // ???? sort array (swap a and b to change order) ???? // Arrays.sort(arr, (a,b) -> b - a ); // System.out.println("main <<< arr: " + Arrays.toString(arr)); // ???? shuffle array ???? // List<Integer> lst = Arrays.asList(arr); // Collections.shuffle(lst); // arr = lst.toArray(new Integer[lst.size()]); // System.out.println("main <<< arr: " + Arrays.toString(arr)); // **** sort array **** quicksort(arr, (a, b) -> a - b); // **** display sorted array **** System.out.println("main <<< arr: " + Arrays.toString(arr)); }

We declare arr[] and populate it with 19 values following no specific order. Some values are repeated.

Our test program displays the count of elements and the contents of the actual array.

Two sets of lines of code follow. We have seen the results of shown such lines in operation.

We then call the quicksort entry point. It has two arguments. The first is the array of integers and the second a comparator. The comparator is used to allow the algorithm to sort two values each time the need arises.

Finally we display the resulting (**hopefully sorted**) array of integers.

/** * Utility function. * Swaps two entries in the array. */ private static <E> void swap(E[] array, int i, int j) { if (i == j) return; E temp = array[i]; array[i] = array[j]; array[j] = temp; }

Most sorting algorithms tend to move data in the same or between data structures. In our case we will be sorting the data in place. We do not require additional space. This utility function is used to swap two values in the array. Note that the contents of the array could be different data types or objects. Of course the comparator passed to the quicksort function / method would have to be **adjusted** to the specific class of object. In our case we use Integers.

/** * Entry point for recursive call. */ public static <E> void quicksort(E[] array, Comparator<E> comparator) { // **** reset counter **** count = 0; // **** recursive call **** quicksort(array, 0, array.length, comparator); // **** display counter **** System.out.println("quicksort <<< count: " + count); }

This is the entry point for the quicksort algorithm. Note that we initialize and later display the value of a counter. In addition we need to pass the start and end values in the array for each pass of the recursive call which we will be looking at it next.

/** * Recursive call * * Time complexity: * Best: (n log(n)) Average: Θ(n log(n)) Worst: O(n^2) * * Space complexity: * O(log(n)) */ private static <E> void quicksort(E[] array, int start, int end, Comparator<E> comparator) { // ???? ???? // System.out.println("quicksort <<< start: " + start + " end: " + end); // **** end condition **** if (end - start <= 0) return; // **** choose a random pivot (optimization technique) **** // int pivotIndex = (int)((end - start) * Math.random()) + start; // swap(array, pivotIndex, end - 1); // **** initialization **** int i = start; int j = end - 1; boolean movingI = true; // **** sort **** while (i < j) { // **** count this operation **** count++; // **** **** if (comparator.compare(array[i], array[j]) > 0) { swap(array, i, j); movingI = !movingI; } else { if (movingI) { i++; } else { j--; } } } // **** recursion **** quicksort(array, start, i, comparator); quicksort(array, i + 1, end, comparator); }

This is the recursive quicksort method. We start by defining our base case.

The next two lines have been commented out. We will talk about them later. They implement an optimization step.

The initialization sets three variables. They are used to traverse elements in the array. We will be pivoting from right to left so the variable **movingI** will be used to signal if we are pivoting on the variable ‘I’ or ‘j’.

The loop is used to swap array entries. The idea is to move all smaller variables from a pivoting point to the other side.

After each pass we repeat the operation with the left and right sides of the array. We are using a divide and conquer approach.

At this time I suggest spending some time **reading** the description of the quicksort algorithm in Wikipedia, **watching** the animated visualization and **following** the code we have in this post.

Once you are fine with the code, enable the optimization. Run the code and observe the results. My suggestion is to leave the optimization enabled.

After that, see if you have some time to spend experimenting by sorting the **input** array in **ascending** and **descending** orders. The count value will change. You can also experiment changing the values in the array and changing the size of the array.

One last thing, many thanks to all **5,825** subscribers to this blog!!!

Regards;

John

**john.canessa@gmail.com**