Algorithms

Lakukan tugas rumah & ujian kamu dengan baik sekarang menggunakan Quizwiz!

Reverse a String

//Reverse a string public static class ReverseString { public static string Reverse(string x) { string result = ""; for (int i = x.Length - 1; i >= 0; i--) result += x[i]; return result; } }

Given a string, find the length of the longest substring without repeating characters. Example 1: Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2: Input: "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1. Example 3: Input: "pwwkew" Output: 3 Explanation: The answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

Approach 1: Brute Force public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); int ans = 0; for (int i = 0; i < n; i++) for (int j = i + 1; j <= n; j++) if (allUnique(s, i, j)) ans = Math.max(ans, j - i); return ans; } public boolean allUnique(String s, int start, int end) { Set<Character> set = new HashSet<>(); for (int i = start; i < end; i++) { Character ch = s.charAt(i); if (set.contains(ch)) return false; set.add(ch); } return true; } } Approach 2: Sliding Window public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); Set<Character> set = new HashSet<>(); int ans = 0, i = 0, j = 0; while (i < n && j < n) { // try to extend the range [i, j] if (!set.contains(s.charAt(j))){ set.add(s.charAt(j++)); ans = Math.max(ans, j - i); } else { set.remove(s.charAt(i++)); } } return ans; } } Approach 3: Sliding Window Optimized public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(), ans = 0; Map<Character, Integer> map = new HashMap<>(); // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { if (map.containsKey(s.charAt(j))) { i = Math.max(map.get(s.charAt(j)), i); } ans = Math.max(ans, j - i + 1); map.put(s.charAt(j), j + 1); } return ans; } } Java (Assuming ASCII 128) public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(), ans = 0; int[] index = new int[128]; // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { i = Math.max(index[s.charAt(j)], i); ans = Math.max(ans, j - i + 1); index[s.charAt(j)] = j + 1; } return ans; } } Approach 1: Brute Force Intuition Check all the substring one by one to see if it has no duplicate character. Time complexity : O(n^3)O(n3). To verify if characters within index range [i, j)[i,j) are all unique, we need to scan all of them. Thus, it costs O(j - i)O(j−i) time. Approach 2: Sliding Window Algorithm The naive approach is very straightforward. But it is too slow. So how can we optimize it? In the naive approaches, we repeatedly check a substring to see if it has duplicate character. But it is unnecessary. If a substring s_{ij}sij​ from index ii to j - 1j−1 is already checked to have no duplicate characters. We only need to check if s[j]s[j] is already in the substring s_{ij}sij​. To check if a character is already in the substring, we can scan the substring, which leads to an O(n^2)O(n2) algorithm. But we can do better. By using HashSet as a sliding window, checking if a character in the current can be done in O(1)O(1). A sliding window is an abstract concept commonly used in array/string problems. A window is a range of elements in the array/string which usually defined by the start and end indices, i.e. [i, j)[i,j) (left-closed, right-open). A sliding window is a window "slides" its two boundaries to the certain direction. For example, if we slide [i, j)[i,j) to the right by 11 element, then it becomes [i+1, j+1)[i+1,j+1) (left-closed, right-open). Back to our problem. We use HashSet to store the characters in current window [i, j)[i,j) (j = ij=i initially). Then we slide the index jj to the right. If it is not in the HashSet, we slide jj further. Doing so until s[j] is already in the HashSet. At this point, we found the maximum size of substrings without duplicate characters start with index ii. If we do this for all ii, we get our answer.

Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward. Example 1: Input: 121 Output: true Example 2: Input: -121 Output: false Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome. Example 3: Input: 10 Output: false Explanation: Reads 01 from right to left. Therefore it is not a palindrome. Follow up: Coud you solve it without converting the integer to a string?

public class Solution { public bool IsPalindrome(int x) { // Special cases: // As discussed above, when x < 0, x is not a palindrome. // Also if the last digit of the number is 0, in order to be a palindrome, // the first digit of the number also needs to be 0. // Only 0 satisfy this property. if(x < 0 || (x % 10 == 0 && x != 0)) { return false; } int revertedNumber = 0; while(x > revertedNumber) { revertedNumber = revertedNumber * 10 + x % 10; x /= 10; } // When the length is an odd number, we can get rid of the middle digit by revertedNumber/10 // For example when the input is 12321, at the end of the while loop we get x = 12, revertedNumber = 123, // since the middle digit doesn't matter in palidrome(it will always equal to itself), we can simply get rid of it. return x == revertedNumber || x == revertedNumber/10; } } Approach 1: Revert half of the number Intuition The first idea that comes to mind is to convert the number into string, and check if the string is a palindrome, but this would require extra non-constant space for creating the string which is not allowed by the problem description. Second idea would be reverting the number itself, and then compare the number with original number, if they are the same, then the number is a palindrome. However, if the reversed number is larger than \text{int.MAX}int.MAX, we will hit integer overflow problem. Following the thoughts based on the second idea, to avoid the overflow issue of the reverted number, what if we only revert half of the \text{int}int number? After all, the reverse of the last half of the palindrome should be the same as the first half of the number, if the number is a palindrome. For example, if the input is 1221, if we can revert the last part of the number "1221" from "21" to "12", and compare it with the first half of the number "12", since 12 is the same as 12, we know that the number is a palindrome. Let's see how we could translate this idea into an algorithm. Algorithm First of all we should take care of some edge cases. All negative numbers are not palindrome, for example: -123 is not a palindrome since the '-' does not equal to '3'. So we can return false for all negative numbers. Now let's think about how to revert the last half of the number. For number 1221, if we do 1221 % 10, we get the last digit 1, to get the second to the last digit, we need to remove the last digit from 1221, we could do so by dividing it by 10, 1221 / 10 = 122. Then we can get the last digit again by doing a modulus by 10, 122 % 10 = 2, and if we multiply the last digit by 10 and add the second last digit, 1 * 10 + 2 = 12, it gives us the reverted number we want. Continuing this process would give us the reverted number with more digits. Now the question is, how do we know that we've reached the half of the number? Since we divided the number by 10, and multiplied the reversed number by 10, when the original number is less than the reversed number, it means we've processed half of the number digits.

How to count number of words in a String

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CodingAlgorithms { //Count the number of words in a string (Needs to handle multiple spaces between words) public static class WordCount { public static int Count(string x) { int result = 0; //Trim whitespace from beginning and end of string x = x.Trim(); //Necessary because foreach will execute once with empty string returning 1 if (x == "") return 0; //Ensure there is only one space between each word in the passed string while (x.Contains(" ")) x = x.Replace(" ", " "); //Count the words foreach (string y in x.Split(' ')) result++; return result; } } }

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) P A H N A P L S I I G Y I R And then read line by line: "PAHNAPLSIIGYIR" Write the code that will take a string and make this conversion given a number of rows: string convert(string s, int numRows); Example 1: Input: s = "PAYPALISHIRING", numRows = 3 Output: "PAHNAPLSIIGYIR" Example 2: Input: s = "PAYPALISHIRING", numRows = 4 Output: "PINALSIGYAHRPI" Explanation: P I N A L S I G Y A H R P I

Approach 1: Sort by Row Class Solution { public String convert(String s, int numRows) { if (numRows == 1) return s; List<StringBuilder> rows = new ArrayList<>(); for (int i = 0; i < Math.min(numRows, s.length()); i++) rows.add(new StringBuilder()); int curRow = 0; boolean goingDown = false; for (char c : s.toCharArray()) { rows.get(curRow).append(c); if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; curRow += goingDown ? 1 : -1; } StringBuilder ret = new StringBuilder(); for (StringBuilder row : rows) ret.append(row); return ret.toString(); } Approach 2: Visit by Row class Solution { public String convert(String s, int numRows) { if (numRows == 1) return s; StringBuilder ret = new StringBuilder(); int n = s.length(); int cycleLen = 2 * numRows - 2; for (int i = 0; i < numRows; i++) { for (int j = 0; j + i < n; j += cycleLen) { ret.append(s.charAt(j + i)); if (i != 0 && i != numRows - 1 && j + cycleLen - i < n) ret.append(s.charAt(j + cycleLen - i)); } } return ret.toString(); } }

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'. '.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). Note: s could be empty and contains only lowercase letters a-z. p could be empty and contains only lowercase letters a-z, and characters like . or *. Example 1: Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa". Example 2: Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Approach 1: Recursion class Solution { public boolean isMatch(String text, String pattern) { if (pattern.isEmpty()) return text.isEmpty(); boolean first_match = (!text.isEmpty() && (pattern.charAt(0) == text.charAt(0) || pattern.charAt(0) == '.')); if (pattern.length() >= 2 && pattern.charAt(1) == '*'){ return (isMatch(text, pattern.substring(2)) || (first_match && isMatch(text.substring(1), pattern))); } else { return first_match && isMatch(text.substring(1), pattern.substring(1)); } } } enum Result { TRUE, FALSE } class Solution { Result[][] memo; public boolean isMatch(String text, String pattern) { memo = new Result[text.length() + 1][pattern.length() + 1]; return dp(0, 0, text, pattern); } public boolean dp(int i, int j, String text, String pattern) { if (memo[i][j] != null) { return memo[i][j] == Result.TRUE; } boolean ans; if (j == pattern.length()){ ans = i == text.length(); } else{ boolean first_match = (i < text.length() && (pattern.charAt(j) == text.charAt(i) || pattern.charAt(j) == '.')); if (j + 1 < pattern.length() && pattern.charAt(j+1) == '*'){ ans = (dp(i, j+2, text, pattern) || first_match && dp(i+1, j, text, pattern)); } else { ans = first_match && dp(i+1, j+1, text, pattern); } } memo[i][j] = ans ? Result.TRUE : Result.FALSE; return ans; } }

12. Integer to Roman Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000 Example 6 ans = VI Part a) String[] symbols = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; int[] values = {1000, 900, 500, 400,100,90,50,40,10,9,5,4,1}; part b) for (int i=0; i<=12; ++i) { while (values[i] <= num) { sb.append(symbols[i]); num -= values[i];

Part a) The answer is just like being a cashier gather the terms order what i need like a cashier and what they mean, and special cases in one string array and the values represent everything they are there are 12 values so we go through the string in order just like a cash register symbols dot length which corresponds with the int values length, so were gonna return our answer using a string builder, because we dont know how potentially long it could be part b its surprisingly simple takes out the biggest int it can takes we do a for loop to loop over every value in the symbol set, in there we are going to a while that i'th symbol value is less than the number we're translating, it would concat that roman symbol into the string builder answer and subtract that roman symbol value from the number, so if we had 623 it would look through see that m is greater so it wouldnt go through the loop, next it would go to D and thats less so it adds a D in our string and, subtracts, we get 123 tries the while again, it fails, so it gets to the next value symbol pair and thats C thats less than 123 so takes away 100 while adding it to our sb ans. so then goes gets to x takes it away twice. and that's our cashiers algorithm or greedy algorithm

Add two linked lists Example: Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807. private static LinkedList<int> AddTwoNumbers(LinkedListNode<int> l1, LinkedListNode<int> l2) { LinkedList<int> sumList = new LinkedList<int>(); sumList.AddLast(0); LinkedListNode<int> dummyHead = sumList.First; LinkedListNode<int> p = l1, q = l2, curr = dummyHead; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.Value : 0; int y = (q != null) ? q.Value : 0; int sum = carry + x + y; carry = sum / 10; curr.Value = (sum % 10); sumList.AddLast(0); curr = curr.Next; if (p != null) p = p.Next; if (q != null) q = q.Next; } if (carry > 0) { curr.Value = carry; } return sumList; }

The main heart of the solution is basically pretty simple. basically the carry, and the current value. First you make sure neither of the two list nodes are null if they are, set the value to 0. You can then get the current sum by adding both the current linked list nodes together, plus the carry. Then you update the carry by dividing that sum by ten. Then your current resulting node value you set that to the sum modulus 10 or remainder of sum divided by ten. Next you just set the current node to the next and then set the listnode for both of them to the next node. Then you set this next value to the carry,(This is more or less just if it gets better).

Longest Substring Expand Around Center Function I dont quite understand what this is doing I know its supposed to be expanding arount the center private int expandAroundCenter(String s, int left, int right) { int L = left, R = right; while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) { L--; R++; } return R - L - 1; }

it expands out in while checking if letters to the left (L)and right(R) are equal to eachother and then return the distance between them - 1 and returns the max length it gets with it being the center

Longest Palindrome main function public String longestPalindrome(String s) { if (s == null || s.length() < 1) return ""; int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); int len2 = expandAroundCenter(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); }

basically It checks if the string is empty then it gets the the length of 2 of them you wonder why you need to get 2 but thats because in the first one we check for the odd "aba" the next we have to check for the even "abba" type palindrome making 2n - 1 such centers, so we do the expand around the centers for both of them and then check which is the greater then since we then know it was the center just half the length and plus and minus to get the end and start places respectively, of the longest substring so far, and you just do a s.substring with both start and end, and that's your answer

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). You may assume nums1 and nums2 cannot be both empty. Example 1: nums1 = [1, 3] nums2 = [2] The median is 2.0 Example 2: nums1 = [1, 2] nums2 = [3, 4] The median is (2 + 3)/2 = 2.5

class Solution { public double findMedianSortedArrays(int[] A, int[] B) { int m = A.length; int n = B.length; if (m > n) { // to ensure m<=n int[] temp = A; A = B; B = temp; int tmp = m; m = n; n = tmp; } int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2; while (iMin <= iMax) { int i = (iMin + iMax) / 2; int j = halfLen - i; if (i < iMax && B[j-1] > A[i]){ iMin = i + 1; // i is too small } else if (i > iMin && A[i-1] > B[j]) { iMax = i - 1; // i is too big } else { // i is perfect int maxLeft = 0; if (i == 0) { maxLeft = B[j-1]; } else if (j == 0) { maxLeft = A[i-1]; } else { maxLeft = Math.max(A[i-1], B[j-1]); } if ( (m + n) % 2 == 1 ) { return maxLeft; } int minRight = 0; if (i == m) { minRight = B[j]; } else if (j == n) { minRight = A[i]; } else { minRight = Math.min(B[j], A[i]); } return (maxLeft + minRight) / 2.0; } } return 0.0; } } Approach 1: Recursive Approach To solve this problem, we need to understand "What is the use of median". In statistics, the median is used for: Dividing a set into two equal length subsets, that one subset is always greater than the other. If we understand the use of median for dividing, we are very close to the answer. First let's cut \text{A}A into two parts at a random position ii: left_A | right_A A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1] Since \text{A}A has mm elements, so there are m+1m+1 kinds of cutting (i = 0 \sim mi=0∼m). And we know: \text{len}(\text{left\_A}) = i, \text{len}(\text{right\_A}) = m - ilen(left_A)=i,len(right_A)=m−i. Note: when i = 0i=0, \text{left\_A}left_A is empty, and when i = mi=m, \text{right\_A}right_A is empty. With the same way, cut \text{B}B into two parts at a random position jj: left_B | right_B B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1] Put \text{left\_A}left_A and \text{left\_B}left_B into one set, and put \text{right\_A}right_A and \text{right\_B}right_B into another set. Let's name them \text{left\_part}left_part and \text{right\_part}right_part: left_part | right_part A[0], A[1], ..., A[i-1] | A[i], A[i+1], ..., A[m-1] B[0], B[1], ..., B[j-1] | B[j], B[j+1], ..., B[n-1] If we can ensure: \text{len}(\text{left\_part}) = \text{len}(\text{right\_part})len(left_part)=len(right_part) \max(\text{left\_part}) \leq \min(\text{right\_part})max(left_part)≤min(right_part) then we divide all elements in \{\text{A}, \text{B}\}{A,B} into two parts with equal length, and one part is always greater than the other. Then \text{median} = \frac{\text{max}(\text{left}\_\text{part}) + \text{min}(\text{right}\_\text{part})}{2}median=2max(left_part)+min(right_part)​ To ensure these two conditions, we just need to ensure: i + j = m - i + n - ji+j=m−i+n−j (or: m - i + n - j + 1m−i+n−j+1)if n \geq mn≥m, we just need to set: i = 0 \sim m, j = \frac{m + n + 1}{2} - i \\i=0∼m,j=2m+n+1​−i \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] and \text{A}[i-1] \leq \text{B}[j]A[i−1]≤B[j] ps.1 For simplicity, I presume \text{A}[i-1], \text{B}[j-1], \text{A}[i], \text{B}[j]A[i−1],B[j−1],A[i],B[j] are always valid even if i=0i=0, i=mi=m, j=0j=0, or j=nj=n. I will talk about how to deal with these edge values at last. ps.2 Why n \geq mn≥m? Because I have to make sure jj is non-negative since 0 \leq i \leq m0≤i≤m and j = \frac{m + n + 1}{2} - ij=2m+n+1​−i. If n < mn<m, then jj may be negative, that will lead to wrong result. So, all we need to do is: Searching ii in [0, m][0,m], to find an object ii such that: \qquad \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] and \ \text{A}[i-1] \leq \text{B}[j], A[i−1]≤B[j], where j = \frac{m + n + 1}{2} - ij=2m+n+1​−i And we can do a binary search following steps described below: Set \text{imin} = 0imin=0, \text{imax} = mimax=m, then start searching in [\text{imin}, \text{imax}][imin,imax] Set i = \frac{\text{imin} + \text{imax}}{2}i=2imin+imax​, j = \frac{m + n + 1}{2} - ij=2m+n+1​−i Now we have \text{len}(\text{left}\_\text{part})=\text{len}(\text{right}\_\text{part})len(left_part)=len(right_part). And there are only 3 situations that we may encounter: \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] and \text{A}[i-1] \leq \text{B}[j]A[i−1]≤B[j]Means we have found the object ii, so stop searching. \text{B}[j-1] > \text{A}[i]B[j−1]>A[i]Means \text{A}[i]A[i] is too small. We must adjust ii to get \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i].Can we increase ii?Yes. Because when ii is increased, jj will be decreased.So \text{B}[j-1]B[j−1] is decreased and \text{A}[i]A[i] is increased, and \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] maybe satisfied.Can we decrease ii?No! Because when ii is decreased, jj will be increased.So \text{B}[j-1]B[j−1] is increased and \text{A}[i]A[i] is decreased, and \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] willbe never satisfied.So we must increase ii. That is, we must adjust the searching range to [i+1, \text{imax}][i+1,imax].So, set \text{imin} = i+1imin=i+1, and goto 2. \text{A}[i-1] > \text{B}[j]A[i−1]>B[j]:Means \text{A}[i-1]A[i−1] is too big. And we must decrease ii to get \text{A}[i-1]\leq \text{B}[j]A[i−1]≤B[j].That is, we must adjust the searching range to [\text{imin}, i-1][imin,i−1].So, set \text{imax} = i-1imax=i−1, and goto 2. When the object ii is found, the median is: \max(\text{A}[i-1], \text{B}[j-1]),max(A[i−1],B[j−1]), when m + nm+n is odd \frac{\max(\text{A}[i-1], \text{B}[j-1]) + \min(\text{A}[i], \text{B}[j])}{2},2max(A[i−1],B[j−1])+min(A[i],B[j])​, when m + nm+n is even Now let's consider the edges values i=0,i=m,j=0,j=ni=0,i=m,j=0,j=n where \text{A}[i-1],\text{B}[j-1],\text{A}[i],\text{B}[j]A[i−1],B[j−1],A[i],B[j] may not exist. Actually this situation is easier than you think. What we need to do is ensuring that \text{max}(\text{left}\_\text{part}) \leq \text{min}(\text{right}\_\text{part})max(left_part)≤min(right_part). So, if ii and jj are not edges values (means \text{A}[i-1], \text{B}[j-1],\text{A}[i],\text{B}[j]A[i−1],B[j−1],A[i],B[j] all exist), then we must check both \text{B}[j-1] \leq \text{A}[i]B[j−1]≤A[i] and \text{A}[i-1] \leq \text{B}[j]A[i−1]≤B[j]. But if some of \text{A}[i-1],\text{B}[j-1],\text{A}[i],\text{B}[j]A[i−1],B[j−1],A[i],B[j] don't exist, then we don't need to check one (or both) of these two conditions. For example, if i=0i=0, then \text{A}[i-1]A[i−1] doesn't exist, then we don't need to check \text{A}[i-1] \leq \text{B}[j]A[i−1]≤B[j]. So, what we need to do is: Searching ii in [0, m][0,m], to find an object ii such that: (j = 0(j=0 or i = mi=m or \text{B}[j-1] \leq \text{A}[i])B[j−1]≤A[i]) and(i = 0(i=0 or j = nj=n or \text{A}[i-1] \leq \text{B}[j]),A[i−1]≤B[j]), where j = \frac{m + n + 1}{2} - ij=2m+n+1​−i And in a searching loop, we will encounter only three situations: (j = 0(j=0 or i = mi=m or \text{B}[j-1] \leq \text{A}[i])B[j−1]≤A[i]) and(i = 0(i=0 or j = nj=n or \text{A}[i-1] \leq \text{B}[j])A[i−1]≤B[j])Means ii is perfect, we can stop searching. j > 0j>0 and i < mi<m and \text{B}[j - 1] > \text{A}[i]B[j−1]>A[i]Means ii is too small, we must increase it. i > 0i>0 and j < nj<n and \text{A}[i - 1] > \text{B}[j]A[i−1]>B[j]Means ii is too big, we must decrease it. Thanks to @Quentin.chen for pointing out that: i < m \implies j > 0i<m⟹j>0 and i > 0 \implies j < ni>0⟹j<n. Because: m \leq n, i < m \implies j = \frac{m+n+1}{2} - i > \frac{m+n+1}{2} - m \geq \frac{2m+1}{2} - m \geq 0m≤n,i<m⟹j=2m+n+1​−i>2m+n+1​−m≥22m+1​−m≥0 m \leq n, i > 0 \implies j = \frac{m+n+1}{2} - i < \frac{m+n+1}{2} \leq \frac{2n+1}{2} \leq nm≤n,i>0⟹j=2m+n+1​−i<2m+n+1​≤22n+1​≤n So in situation 2. and 3. , we don't need to check whether j > 0j>0 and whether j < nj<n.

Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321

class Solution { public int reverse(int x) { int rev = 0; while (x != 0) { int pop = x % 10; x /= 10; if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0; if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0; rev = rev * 10 + pop; } return rev; } }

Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321 Example 2: Input: -123 Output: -321 Example 3: Input: 120 Output: 21 Note:Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

class Solution { public int reverse(int x) { int rev = 0; while (x != 0) { int pop = x % 10; x /= 10; if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0; if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0; rev = rev * 10 + pop; } return rev; } } Approach 1: Pop and Push Digits & Check before Overflow Intuition We can build up the reverse integer one digit at a time. While doing so, we can check beforehand whether or not appending another digit would cause overflow. Algorithm Reversing an integer can be done similarly to reversing a string. We want to repeatedly "pop" the last digit off of xx and "push" it to the back of the \text{rev}rev. In the end, \text{rev}rev will be the reverse of the xx. To "pop" and "push" digits without the help of some auxiliary stack/array, we can use math. //pop operation: pop = x % 10; x /= 10; //push operation: temp = rev * 10 + pop; rev = temp; However, this approach is dangerous, because the statement \text{temp} = \text{rev} \cdot 10 + \text{pop}temp=rev⋅10+pop can cause overflow. Luckily, it is easy to check beforehand whether or this statement would cause an overflow. To explain, lets assume that \text{rev}rev is positive. If temp = \text{rev} \cdot 10 + \text{pop}temp=rev⋅10+pop causes overflow, then it must be that \text{rev} \geq \frac{INTMAX}{10}rev≥10INTMAX​ If \text{rev} > \frac{INTMAX}{10}rev>10INTMAX​, then temp = \text{rev} \cdot 10 + \text{pop}temp=rev⋅10+pop is guaranteed to overflow. If \text{rev} == \frac{INTMAX}{10}rev==10INTMAX​, then temp = \text{rev} \cdot 10 + \text{pop}temp=rev⋅10+pop will overflow if and only if \text{pop} > 7pop>7 Similar logic can be applied when \text{rev}rev is negative.

12. Integer to Roman Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000 For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven 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. Input is guaranteed to be within the range from 1 to 3999. Example 1: Input: 3 Output: "III"

class Solution { public String intToRoman(int num) { String[] symbols = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; int[] values = {1000, 900, 500, 400,100,90,50,40,10,9,5,4,1}; StringBuilder sb = new StringBuilder(); for (int i=0; i<=12; ++i) { while (values[i] <= num) { sb.append(symbols[i]); num -= values[i]; } } return sb.toString(); } }

ATOI which converts a string to an integer.

first there is really just a string.convert and then just make sure its < Math.power(2,31) -1 and greater than -Math.power(2,31) then if you really just wanna do it first thought would be to do a cashier's algorithm or greedy algorithm, it's not necessary if you know a little bit of computer science, everything is already numbers so you just subtract it from its '0' and you've converted its single digit, so then the algorithm is super simple do a for loop over the string for i = 0 semicolon i less than string to be converted dot length i plus plus curly brace converted string equals converted string times ten plus string to be converted i'th char minus char 0, thats it

Determine if Two Words Are Anagrams of Each Other

namespace Anagram { class Program { static void Main(string[] args) { //Receive Words from User Console.Write("Enter first word:"); string word1 = Console.ReadLine(); Console.Write("Enter second word:"); string word2 = Console.ReadLine(); //Add optional validation of input words if needed. //..... //step 1 char[] char1 = word1.ToLower().ToCharArray(); char[] char2 = word2.ToLower().ToCharArray(); //Step 2 Array.Sort(char1); Array.Sort(char2); //Step 3 string NewWord1 = new string(char1); string NewWord2 = new string(char2); //Step 4 //ToLower allows to compare the words in same case, in this case, lower case. //ToUpper will also do exact same thing in this context if (NewWord1 == NewWord2) { Console.WriteLine("Yes! Words \"{0}\" and \"{1}\" are Anagrams", word1, word2); } else { Console.WriteLine("No! Words \"{0}\" and \"{1}\" are not Anagrams", word1, word2); } //Hold Console screen alive to view the results. Console.ReadLine(); } } }

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example 1: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Example 2: Input: "cbbd" Output: "bb"

number 5 public String longestPalindrome(String s) { if (s == null || s.length() < 1) return ""; int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); int len2 = expandAroundCenter(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); } private int expandAroundCenter(String s, int left, int right) { int L = left, R = right; while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) { L--; R++; } return R - L - 1; } Approach 4: Expand Around Center In fact, we could solve it in O(n^2)O(n2) time using only constant space. We observe that a palindrome mirrors around its center. Therefore, a palindrome can be expanded from its center, and there are only 2n - 12n−1 such centers. You might be asking why there are 2n - 12n−1 but not nn centers? The reason is the center of a palindrome can be in between two letters. Such palindromes have even number of letters (such as "abba") and its center are between the two 'b's. Approach 1: Longest Common Substring Common mistake Some people will be tempted to come up with a quick solution, which is unfortunately flawed (however can be corrected easily): Reverse SS and become S'S′. Find the longest common substring between SS and S'S′, which must also be the longest palindromic substring. This seemed to work, let's see some examples below. For example, SS = "caba", S'S′ = "abac". The longest common substring between SS and S'S′ is "aba", which is the answer. Let's try another example: SS = "abacdfgdcaba", S'S′ = "abacdgfdcaba". The longest common substring between SS and S'S′ is "abacd". Clearly, this is not a valid palindrome. Algorithm We could see that the longest common substring method fails when there exists a reversed copy of a non-palindromic substring in some other part of SS. To rectify this, each time we find a longest common substring candidate, we check if the substring's indices are the same as the reversed substring's original indices. If it is, then we attempt to update the longest palindrome found so far; if not, we skip this and find the next candidate. This gives us an O(n^2)O(n2) Dynamic Programming solution which uses O(n^2)O(n2) space (could be improved to use O(n)O(n) space). Please read more about Longest Common Substring

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Example: Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation: 342 + 465 = 807.

private static LinkedList<int> AddTwoNumbers(LinkedListNode<int> l1, LinkedListNode<int> l2) { LinkedList<int> sumList = new LinkedList<int>(); sumList.AddLast(0); LinkedListNode<int> dummyHead = sumList.First; LinkedListNode<int> p = l1, q = l2, curr = dummyHead; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.Value : 0; int y = (q != null) ? q.Value : 0; int sum = carry + x + y; carry = sum / 10; curr.Value = (sum % 10); sumList.AddLast(0); curr = curr.Next; if (p != null) p = p.Next; if (q != null) q = q.Next; } if (carry > 0) { curr.Value = carry; } return sumList; } Approach 1: Elementary Math Intuition Keep track of the carry using a variable and simulate digits-by-digits sum starting from the head of list, which contains the least-significant digit. Figure 1. Visualization of the addition of two numbers: 342 + 465 = 807342+465=807.Each node contains a single digit and the digits are stored in reverse order. Algorithm Just like how you would sum two numbers on a piece of paper, we begin by summing the least-significant digits, which is the head of l1l1 and l2l2. Since each digit is in the range of 0 \ldots 90...9, summing two digits may "overflow". For example 5 + 7 = 125+7=12. In this case, we set the current digit to 22 and bring over the carry = 1carry=1 to the next iteration. carrycarry must be either 00 or 11 because the largest possible sum of two digits (including the carry) is 9 + 9 + 1 = 199+9+1=19. The pseudocode is as following: Initialize current node to dummy head of the returning list. Initialize carry to 00. Initialize pp and qq to head of l1l1 and l2l2 respectively. Loop through lists l1l1 and l2l2 until you reach both ends.Set xx to node pp's value. If pp has reached the end of l1l1, set to 00.Set yy to node qq's value. If qq has reached the end of l2l2, set to 00.Set sum = x + y + carrysum=x+y+carry.Update carry = sum / 10carry=sum/10.Create a new node with the digit value of (sum \bmod 10)(summod10) and set it to current node's next, then advance current node to next.Advance both pp and qq. Check if carry = 1carry=1, if so append a new node with digit 11 to the returning list. Return dummy head's next node. Note that we use a dummy head to simplify the code. Without a dummy head, you would have to write extra conditional statements to initialize the head's value. Take extra caution of the following cases:

Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. Note: You may not slant the container and n is at least 2. The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. Example: Input: [1,8,6,2,5,4,8,3,7] Output: 49

public class Solution { public int maxArea(int[] height) { int maxarea = 0, l = 0, r = height.length - 1; while (l < r) { maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l)); if (height[l] < height[r]) l++; else r--; } return maxarea; } } https://leetcode.com/problems/container-with-most-water/solution/ Summary We have to maximize the Area that can be formed between the vertical lines using the shorter line as length and the distance between the lines as the width of the rectangle forming the area. Solution Approach 1: Brute Force Algorithm public class Solution { public int maxArea(int[] height) { int maxarea = 0; for (int i = 0; i < height.length; i++) for (int j = i + 1; j < height.length; j++) maxarea = Math.max(maxarea, Math.min(height[i], height[j]) * (j - i)); return maxarea; } } In this case, we will simply consider the area for every possible pair of the lines and find out the maximum area out of those. Complexity Analysis Time complexity : O(n^2)O(n2). Calculating area for all \dfrac{n(n-1)}{2}2n(n−1)​ height pairs. Space complexity : O(1)O(1). Constant extra space is used. Approach 2: Two Pointer Approach Algorithm The intuition behind this approach is that the area formed between the lines will always be limited by the height of the shorter line. Further, the farther the lines, the more will be the area obtained. We take two pointers, one at the beginning and one at the end of the array constituting the length of the lines. Futher, we maintain a variable \text{maxarea}maxarea to store the maximum area obtained till now. At every step, we find out the area formed between them, update \text{maxarea}maxarea and move the pointer pointing to the shorter line towards the other end by one step. The algorithm can be better understood by looking at the example below: 1 8 6 2 5 4 8 3 7 1 / 8 How this approach works? Initially we consider the area constituting the exterior most lines. Now, to maximize the area, we need to consider the area between the lines of larger lengths. If we try to move the pointer at the longer line inwards, we won't gain any increase in area, since it is limited by the shorter line. But moving the shorter line's pointer could turn out to be beneficial, as per the same argument, despite the reduction in the width. This is done since a relatively longer line obtained by moving the shorter line's pointer might overcome the reduction in area caused by the width reduction. For further clarification click here and for the proof click here. Complexity Analysis Time complexity : O(n)O(n). Single pass. Space complexity : O(1)O(1). Constant space is used.

implement atoi which converts a string to an integer. The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value. The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function. If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed. If no valid conversion could be performed, a zero value is returned. Note: Only the space character ' ' is considered as whitespace character. Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned. Example 1: Input: "42" Output: 42 Example 2: Input: " -42" Output: -42 Explanation: The first non-whitespace character is '-', which is the minus sign. Then take as many numerical digits as possible, which gets 42.

var myAtoi = function (str) { let ret = 0; let INT_MAX = Math.pow(2, 31) - 1; let INT_MIN = -Math.pow(2, 31); let inputVal = parseInt(str.trim()); if (Number.isInteger(inputVal)) { if ((inputVal < INT_MAX) && (inputVal > INT_MIN)) { ret = inputVal; } else if (inputVal >= INT_MAX) { ret = INT_MAX; } else { ret = INT_MIN; } } return ret; }; int myAtoi(char* str) { int res = 0; // Initialize result int sign = 1; // Initialize sign as positive int i = 0; // Initialize index of first digit // If number is negative, then update sign if (str[0] == '-') { sign = -1; i++; // Also update index of first digit } // Iterate through all digits and update the result for (; str[i] != '\0'; ++i) res = res * 10 + str[i] - '0'; // Return result with sign return sign * res; } // Driver code int main() { char str[] = "-123"; int val = myAtoi(str); cout << val; return 0; }


Set pelajaran terkait

Child with an integumentary disorder

View Set

SS.7.C.1.4: Natural Rights and Declaration of Independence

View Set

Fluid and Electrolyte/Thermoregulation

View Set

Academic League Practice Toss Up Questions

View Set

LET Specialization: Social Studies

View Set