Thursday, January 14, 2021

LeetCode: Boats to Save People Solution

 The problem statement is copy pasted from leetcode as it is:


The i-th person has weight people[i], and each boat can carry a maximum weight of limit.

Each boat carries at most 2 people at the same time, provided the sum of the weight of those people is at most limit.

Return the minimum number of boats to carry every given person.  (It is guaranteed each person can be carried by a boat.)

 

Example 1:

Input: people = [1,2], limit = 3
Output: 1
Explanation: 1 boat (1, 2)

Example 2:

Input: people = [3,2,2,1], limit = 3
Output: 3
Explanation: 3 boats (1, 2), (2) and (3)

Example 3:

Input: people = [3,5,3,4], limit = 5
Output: 4
Explanation: 4 boats (3), (3), (4), (5)

Note:

  • 1 <= people.length <= 50000
  • 1 <= people[i] <= limit <= 30000

My Solution:
package madwani.sushil.leetcode.Jan_8_15_2021;

import java.util.Arrays;

public class BoatsToSavePeople {
public static void main(String[] args) {
int[] people = new int[] {3,5,3,4}; // 4
int[] people1 = new int[] {1,2}; // 1
int[] people2 = new int[] {3,2,2,1}; // 3
int[] people3 = new int[] {2,4}; // 2
int[] people4 = new int[] {2,2}; // 1
int[] people5 = new int[] {1,1,1}; // 2
System.out.println(numRescueBoats(people, 5));
System.out.println(numRescueBoats(people1, 3));
System.out.println(numRescueBoats(people2, 3));
System.out.println(numRescueBoats(people3, 5));
System.out.println(numRescueBoats(people4, 6));
System.out.println(numRescueBoats(people5, 3));
}

// Time Complexity : O(NLogN), Space Complexity : O(1)
static int numRescueBoats(int[] people, int limit) {
int numBoats = 0;
// sort people based on weight
Arrays.sort(people);
int i = 0, j = people.length-1;
while (i <=j) {
numBoats++;
// as max 2 people can be carried at time
// it is always better to carry heaviest and lightest person at a time.
if (people[i] + people[j] <= limit) {
// if both can be carried, moved to the next lightest person
i++;
}
// always heaviest person will be carried definitely so moved to the next heaviest person
j--;
}
return numBoats;
}
}

Wednesday, January 13, 2021

LeetCode: Roman To Integer

 The problem statement is copy pasted from leetcode as it is:


Roman numerals are represented by seven different symbols: IVXLCD and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9. 
  • X can be placed before L (50) and C (100) to make 40 and 90. 
  • C can be placed before D (500) and M (1000) to make 400 and 900.

Given a roman numeral, convert it to an integer.

 

Example 1:

Input: s = "III"
Output: 3

Example 2:

Input: s = "IV"
Output: 4

Example 3:

Input: s = "IX"
Output: 9

Example 4:

Input: s = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Example 5:

Input: s = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

 

Constraints:

  • 1 <= s.length <= 15
  • s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
  • It is guaranteed that s is a valid roman numeral in the range [1, 3999].


My Solution for the problem is:

package madwani.sushil.leetcode.Amazon;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class RomanToInteger {

public static void main(String[] args) {
System.out.println(romanToInt("XVI")); // 16
System.out.println(romanToInt("LVIII")); // 58
System.out.println(romanToInt("MCMXCIV")); // 1994
}

public static int romanToInt(String roman) {
Map<String, Integer> map = new HashMap<>();
int num = 0;
map.put("I", 1);
map.put("IV", 4);
map.put("V", 5);
map.put("IX", 9);
map.put("X", 10);
map.put("XL", 40);
map.put("L", 50);
map.put("XC", 90);
map.put("C", 100);
map.put("CD", 400);
map.put("D", 500);
map.put("CM", 900);
map.put("M", 1000);
for (int i = roman.length() - 1; i >= 0; i--) {
if (i-1 >= 0 && map.get(roman.substring(i-1, i+1)) != null) {
num += map.get(roman.substring(i - 1, i+1));
i = i - 1;
} else {
num += map.get(roman.substring(i, i+1));
}
}
return num;
}
}

Tuesday, January 12, 2021

LeetCode: Merge Sorted Array

 Problem statement is copy pasted from leetcode as it is:


Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

The number of elements initialized in nums1 and nums2 are m and n respectively. You may assume that nums1 has enough space (size that is equal to m + n) to hold additional elements from nums2.

 

Example 1:

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]

Example 2:

Input: nums1 = [1], m = 1, nums2 = [], n = 0
Output: [1]

 

Constraints:

  • 0 <= n, m <= 200
  • 1 <= n + m <= 200
  • nums1.length == m + n
  • nums2.length == n
  • -109 <= nums1[i], nums2[i] <= 109

My Solution:

package madwani.sushil.leetcode.Jan_8_15_2021;

public class MergeSortedArray {
public static void main(String[] args) {
int [] nums1 = new int[] {1, 2, 3, 0, 0, 0};
int [] nums2 = new int[] {2, 5, 6};
int [] nums12 = new int[] {1};
int [] nums22 = new int[] {};
int [] nums13 = new int[] {4,0,0,0,0,0};
int [] nums23 = new int[] {1,2,3,5,6};
int [] nums14 = new int[] {1,2,4,5,6,0};
int [] nums24 = new int[] {3};
int [] nums15 = new int[] {0,0,3,0,0,0,0,0,0};
int [] nums25 = new int[] {-1,1,1,1,2,3};
merge1(nums1, 3, nums2, 3);
merge1(nums12, 1, nums22, 0);
merge1(nums13, 1, nums23, 5);
merge1(nums14, 5, nums24, 1);
merge1(nums15, 3, nums25, 6);
System.out.println("done");
}

// its a single pass with O(1) space complexity
public static void merge1(int[] nums1, int m, int[] nums2, int n) {
m = m-1; // pointer to last element of num1
n = n-1; // pointer to last element of num2

// total number of elements
int i = nums1.length - 1;

// iterating from end of each array till we reach start of any array
while ( n >= 0 && m >=0) {
if (nums2[n] > nums1[m]) {
nums1[i--] = nums2[n--];
} else {
nums1[i--] = nums1[m--];
}
}
// if second array is still left with the elements
while (n >= 0) {
nums1[i--] = nums2[n--];
}
}

// with space complexity O(N)
public static void merge(int[] nums1, int m, int[] nums2, int n) {
if ( n == 0) {
return;
}
int i =0, j=0;
while (i < m && j < n) {
if (nums1[i] <= nums2[j]) i++;
else {
insert(nums1, i, nums2[j]);
m++;
j++;
}
}
while (i < nums1.length && j < n) {
if (nums1[i] !=0) i++;
else nums1[i++] = nums2[j++];
}

}

public static void insert(int[] nums1, int position, int tNum) {
while (position < nums1.length) {
int temp = nums1[position];
nums1[position++] = tNum;
tNum = temp;
}
}
}

Sunday, January 10, 2021

LeetCode: Word Ladder ( Well Commented solution)

 The Question statement is copy pasted from leet code as it is:


Given two words beginWord and endWord, and a dictionary wordList, return the length of the shortest transformation sequence from beginWord to endWordsuch that:

  • Only one letter can be changed at a time.
  • Each transformed word must exist in the word list.

Return 0 if there is no such transformation sequence.

 

Example 1:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.

Example 2:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

 

Constraints:

  • 1 <= beginWord.length <= 100
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • wordList[i].length == beginWord.length
  • beginWordendWord, and wordList[i] consist of lowercase English letters.
  • beginWord != endWord
  • All the strings in wordList are unique.

My Solution :

package madwani.sushil.leetcode.Jan_8_15_2021;

import java.util.*;

public class WordLadder {
public static void main(String[] args) {
String[] wordList = new String[] {"a","b","c"};
String beginWord = "a";
String endWord = "c";
String[] wordList1 = new String[] { "hot","dot","dog","lot","log","cog" };
String beginWord1 = "hit";
String endWord1 = "cog";
String[] wordList2 = new String[] { "hot","dog"};
String beginWord2 = "hot";
String endWord2 = "dog";
System.out.println(ladderLength1(beginWord, endWord, Arrays.asList(wordList))); // 2
System.out.println(ladderLength1(beginWord1, endWord1, Arrays.asList(wordList1))); // 5
System.out.println(ladderLength1(beginWord2, endWord2, Arrays.asList(wordList2))); // 1
}
// we are using Breadth First Search to find the shortest word transformation
// time complexity is O (wordList size * wordLength * wordLength) - explained at each step
public static int ladderLength1(String beginWord, String endWord, List<String> wordList) {
Set<String> words = new HashSet<>(wordList);
if (!words.contains(endWord)) return 0;
// we will use queue to track the levels as we move ahead to find the end word
Queue<String> wordQueue = new LinkedList<>();
wordQueue.add(beginWord);

// visited set is maintained for string already visited and counted
Set<String> visited = new HashSet<>();

// as we already added the begin word in it, so we are at level of search
int level = 1;
//visited.add(beginWord);
while (!wordQueue.isEmpty()) { // the time complexity of this operation would be O(input word list size)
// now lets go deep inside at each level
// every level contain words which have 1 char from previous level
// as we are going for next level, lets increase the level
level++;
int size = wordQueue.size();
// we need to work on all words on that level
while(size-- > 0) {
String wordToSearch = wordQueue.poll();
// below will add it to visited queue and run the algo
// if already exist it will ignore that word and won't run the algo
if (visited.add(wordToSearch)) {
// major work is happening here
// we are trying to make all possible combination of the word
for (int i=0; i < wordToSearch.length(); i++) { // here the time complexity is O(length of the word)
char[] chars = wordToSearch.toCharArray();
char[] temp = wordToSearch.toCharArray();
for (char ch = 'a'; ch <= 'z'; ch++) {
if (ch == chars[i]) continue;
temp[i] = ch;
String str = new String(temp);
// if that combination is part of the input word list
if (words.contains(str)) {
// and if that is the end word, we are done
if (str.equals(endWord)) return level; // the comparision time complexity is O(length of the word)
// else add that into the queue for the next level search
wordQueue.add(str);
}
}
} // this loop will be having time complexity of O(wordlength * wordlength)
}
}
} // this loop total time complexity would be O(listsize * wordLength * wordlength)
return 0;
}
}

Saturday, January 9, 2021

LeetCode: Integer to Roman

 The Problem statement is copy pasted from leetcode as it is.

Roman numerals are represented by seven different symbols: IVXLCD and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9. 
  • X can be placed before L (50) and C (100) to make 40 and 90. 
  • C can be placed before D (500) and M (1000) to make 400 and 900.

Given an integer, convert it to a roman numeral.

 

Example 1:

Input: num = 3
Output: "III"

Example 2:

Input: num = 4
Output: "IV"

Example 3:

Input: num = 9
Output: "IX"

Example 4:

Input: num = 58
Output: "LVIII"
Explanation: L = 50, V = 5, III = 3.

Example 5:

Input: num = 1994
Output: "MCMXCIV"
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

 

Constraints:

  • 1 <= num <= 3999

My Solution:

package madwani.sushil.leetcode.Amazon;

import java.util.HashMap;
import java.util.Map;

public class IntegerToRoman {
public static void main(String[] args) {
System.out.println(intToRoman(58));
}

public static String intToRoman(int num) {
Map<Integer, String> map = new HashMap<>();
int i = 1;
int temp;
String result = "";
map.put(0, "");
map.put(1, "I");
map.put(4, "IV");
map.put(5, "V");
map.put(9, "IX");
map.put(10, "X");
map.put(40, "XL");
map.put(50, "L");
map.put(90, "XC");
map.put(100, "C");
map.put(400, "CD");
map.put(500, "D");
map.put(900, "CM");
map.put(1000, "M");
while (num != 0) {
temp = (num%(10))*i;
if (temp > i && temp < 4*i) {
while (temp >= i) {
result = map.get(i) + result;
temp = temp - i;
}
} else if (temp > 5*i && temp < 9*i) {
String res = map.get(5*i);
temp = temp - 5*i;
while (temp >= i) {
res = res + map.get(i);
temp = temp - i;
}
result = res + result;
} else {
result = map.get(temp) + result;
}
i = i*10;
num = num/10;
}
return result;
}
}