Leetcode 4
- [151. Reverse Words in a String](#151. Reverse Words in a String)
- [152. Maximum Product Subarray](#152. Maximum Product Subarray)
- [153. Find Minimum in Rotated Sorted Array](#153. Find Minimum in Rotated Sorted Array)
- [155. Min Stack](#155. Min Stack)
- [160. Intersection of Two Linked Lists](#160. Intersection of Two Linked Lists)
- [161. One Edit Distance](#161. One Edit Distance)
- [162. Find Peak Element](#162. Find Peak Element)
- [165. Compare Version Numbers](#165. Compare Version Numbers)
- [166. Fraction to Recurring Decimal](#166. Fraction to Recurring Decimal)
- [167. Two Sum II - Input Array Is Sorted](#167. Two Sum II - Input Array Is Sorted)
- [168. Excel Sheet Column Title](#168. Excel Sheet Column Title)
- [169. Majority Element](#169. Majority Element)
- [171. Excel Sheet Column Number](#171. Excel Sheet Column Number)
- [172. Factorial Trailing Zeroes](#172. Factorial Trailing Zeroes)
- [173. Binary Search Tree Iterator](#173. Binary Search Tree Iterator)
- [179. Largest Number](#179. Largest Number)
-
-
- [custom sort / compare](#custom sort / compare)
-
- [187. Repeated DNA Sequences](#187. Repeated DNA Sequences)
- [189. Rotate Array](#189. Rotate Array)
- [190. Reverse Bits](#190. Reverse Bits)
- [191. Number of 1 Bits](#191. Number of 1 Bits)
- [198. House Robber](#198. House Robber)
- [199. Binary Tree Right Side View](#199. Binary Tree Right Side View)
- [200. Number of Islands](#200. Number of Islands)
151. Reverse Words in a String
151. Reverse Words in a String
Given an input string s, reverse the order of the words.
A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.
Return a string of the words in reverse order concatenated by a single space.
Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.
Input: s = "the sky is blue"Output: "blue is sky the"
1. split the sentence into word, reverse the word order.
strList: [the, sky, is, blue]
Collections.reverse(strList);
strList: [blue, is, sky, the]
java
class Solution {
public String reverseWords(String s) {
List<String> strList = new ArrayList<>();
StringBuffer temp = new StringBuffer();
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==' '){
if(temp.length()>0){
strList.add(new String(temp.toString()));
temp.delete(0,temp.length());
}
continue;
}
else{
temp.append(s.charAt(i));
}
}
if(temp.length()>0){
strList.add(new String(temp.toString()));
}
Collections.reverse(strList);
StringBuffer ans = new StringBuffer();
for(String str:strList){
ans.append(str);
ans.append(" ");
}
ans.delete(ans.length()-1,ans.length());
return ans.toString();
}
}
6ms 91.02% 42.4MB 87.92%
Use trim() and split() to split the word
java
public String reverseWords(String s) {
Stack<String> st = new Stack<String>();
for (String a : s.trim().split(" ")) {
if (!a.isEmpty())
st.push(a);
}
StringBuilder sb = new StringBuilder();
while (!st.isEmpty()) {
sb.append(st.pop());
sb.append(" ");
}
return sb.toString().trim();
}
9 ms 79.91% 43.3 MB 68.57%
-
StringBuffer
clear the string buffer using the delete() and setLength() method and creating a new StringBuffer object in Java.
** str.delete(0,str.length())**
str.setLength(0) -
Collections.reverse()
Reversing an ArrayList, a LinkedList, an array
-
String split()
java
for (String a : s.trim().split(" ")) {
if (!a.isEmpty())
st.push(a);
}
- String trim()
The trim() method in java checks this Unicode value before and after the string, if it exists then removes the spaces and returns the omitted string.
The trim() method doesn't eliminate middle spaces.
java
String str = "GeeksforGeeks:A Computer Science Portal";
String[] arrOfStr = str.split(":");
GeeksforGeeks
A Computer Science Portal
java
String str = "GeeksforGeeksforStudents";
String[] arrOfStr = str.split("for");
Geeks
Geeks
Students
2. Reverse twice. Reverse the whole sentence + Reverse the word.
the sky is blue
-> eulb si yks eht
-> blue is sky the
java
public class Solution {
public String reverseWords(String s) {
if (s == null) return null;
char[] a = s.toCharArray();
int n = a.length;
// step 1. reverse the whole string
reverse(a, 0, n - 1);
// step 2. reverse each word
reverseWords(a, n);
// step 3. clean up spaces
return cleanSpaces(a, n);
}
void reverseWords(char[] a, int n) {
int i = 0, j = 0;
while (i < n) {
while (i < j || i < n && a[i] == ' ') i++; // skip spaces
while (j < i || j < n && a[j] != ' ') j++; // skip non spaces
reverse(a, i, j - 1); // reverse the word
}
}
// trim leading, trailing and multiple spaces
String cleanSpaces(char[] a, int n) {
int i = 0, j = 0;
while (j < n) {
while (j < n && a[j] == ' ') j++; // skip spaces
while (j < n && a[j] != ' ') a[i++] = a[j++]; // keep non spaces
while (j < n && a[j] == ' ') j++; // skip spaces
if (j < n) a[i++] = ' '; // keep only one space
}
return new String(a).substring(0, i);
}
// reverse a[] from a[i] to a[j]
private void reverse(char[] a, int i, int j) {
while (i < j) {
char t = a[i];
a[i++] = a[j];
a[j--] = t;
}
}
}
152. Maximum Product Subarray
Given an integer array nums, find a subarray that has the largest product, and return the product.
The test cases are generated so that the answer will fit in a 32-bit integer.
Example 1:Input: nums = [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:
Input: nums = [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
- Case1 :All the elements are positive : Then your answer will be product of all the elements in the array.
- Case2 : Array have positive and negative elements both :
If the number of negative elements is even then again your answer will be complete array.
If the number of negative elements is odd then you have to remove just one negative element and for that u need to check your subarrays to get the max product. - Case3 : Array also contains 0 : Then there will be not much difference...its just that your array will be divided into subarray around that 0.
-1, -2, -3
-1,-2 \] : max: 1 min: -2 \[ -1, -2, -3 \] : max: (-2) \* (-3) = 6 min: 2 \* (-3) = -6 \[ -1, -2, -3, 4 \] : max: 4 \* 6 = 24 min: 4 \* (-6) = -24 \[ -1, -2, -3, -4 \] : max: (-4) \* (-6) = 24 min: (-4) \* (6) = -24
java
class Solution {
public int maxProduct(int[] nums) {
int max = nums[0], min = nums[0], ans = nums[0];
for (int i = 1; i < nums.length; i++) {
int temp = max; // store the max because before updating min your max will already be updated
max = Math.max(Math.max(max * nums[i], min * nums[i]), nums[i]);
min = Math.min(Math.min(temp * nums[i], min * nums[i]), nums[i]);
if (max > ans) {
ans = max;
}
}
return ans;
}
}
153. Find Minimum in Rotated Sorted Array
153. Find Minimum in Rotated Sorted Array
Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:
4,5,6,7,0,1,2\] if it was rotated 4 times. \[0,1,2,4,5,6,7\] if it was rotated 7 times. Notice that rotating an array \[a\[0\], a\[1\], a\[2\], ..., a\[n-1\]\] 1 time results in the array \[a\[n-1\], a\[0\], a\[1\], a\[2\], ..., a\[n-2\]\]. Given the sorted rotated array nums of unique elements, return the minimum element of this array. You must write an algorithm that runs in O(log n) time. Example 1: Input: nums = \[3,4,5,1,2
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Example 2:
Input: nums = [4,5,6,7,0,1,2]
Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Example 3:
Input: nums = [11,13,15,17]
Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times.
Constraints:n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
All the integers of nums are unique.
nums is sorted and rotated between 1 and n times.
low mid high
if(low<high) min = low
if(low<mid) low mid min (mid > high)/ low min mid(mid<high)
Binary Search
java
public int findMin(int[] nums) {
int low = 0;
int high = nums.length-1;
int mid;
if(nums.length==1){
return nums[0];
}
//A 递增 最小 递增 B A>B
if(nums[low]<nums[high]){
//最小递增B
return nums[low];
}
//low=high return low
while(low<high){
mid = low+(high-low)/2;
//A 递增 最小 递增 B 递增时后一位都比前一位大 比前一位小的是第二个递增序列开始那一位 即最小
if(mid>0 && nums[mid]<nums[mid-1]){
return nums[mid];
}
//把mid==low包含其中 low high 当mid==low时 nums[mid]>nums[high] 即high为最小
//if(nums[mid]>=nums[low] && nums[mid]>nums[high]){
if(nums[mid]>nums[low] && nums[mid]>nums[high]){
low = mid +1;
}
else if(nums[mid]==nums[low] && nums[mid]>nums[high]){
return nums[high];
}
else{
high = mid -1;
}
}
return nums[low];
}
155. Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
Implement the MinStack class:
MinStack() initializes the stack object.
void push(int val) pushes the element val onto the stack.
void pop() removes the element on the top of the stack.
int top() gets the top element of the stack.
int getMin() retrieves the minimum element in the stack.
You must implement a solution with O(1) time complexity for each function.
Stack
two stack
java
class MinStack {
//设置最小值栈 每个结点存储当前深度内的最小值
//Math.min(minStack.peek(),val)
//5ms 81.21%
Stack<Integer> minStack;
Stack<Integer> stack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
if(minStack.isEmpty()){
minStack.push(val);
}
else{
minStack.push(Math.min(minStack.peek(),val));
}
stack.push(val);
}
public void pop() {
stack.pop();
minStack.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
one stack, push pre min into stack as along as current item
java
class MinStack {
//将最小值的更新存入同一个栈中
Stack<Integer> stack=new Stack<>();
int min=Integer.MAX_VALUE;
public void push(int x) {
//出现新的最小值时,存储上一任最小值进同样一个栈 方便出栈更新最小值
if(x<=min) {
stack.push(min);
min=x;
}
stack.push(x);
}
public void pop() {
if(stack.peek()==min){
stack.pop();
min=stack.pop(); //上一任最小值存储在当前最小值的下一个结点
}
else stack.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return min;
}
}
Custom Structure
java
class MinStack {
//不使用栈 自定义了一个链式结构
//设置一个参数记录每次新进的结点和原最小值之间的最小值
// 3ms 99.66%
class Node{
int val;
int min;
Node next;
public Node(int val , int min , Node next){
this.val = val;
this.min = min;
this.next = next;
}
}
private Node head;
public MinStack() {
head = null;
}
//栈 先进后出 进去的结点的next指向之前的结点 更新head指向最新进去的结点
/* head / top
|
V
new node
|
V
old node
*/
public void push(int val) {
if(head == null)
head = new Node(val ,val ,null);
else
head = new Node(val , Math.min(val ,head.min), head);
}
public void pop() {
head = head.next;
}
public int top() {
return head.val;
}
public int getMin() {
return head.min;
}
}
160. Intersection of Two Linked Lists
160. Intersection of Two Linked Lists
Given the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.
For example, the following two linked lists begin to intersect at node c1:
The test cases are generated such that there are no cycles anywhere in the entire linked structure.
遍历第一个链表到尾部,连接到第二个链表
- 如果两个链表不相交,相连之后,还是一个单链表
- 如果两个链表相交,相连之后会有环
-
get the len of the A,B. Use two pointer F,S. F-S = | lenA-lenB |
A.next == B.next
-
len A+B = len B+A
len a+c+b+c = b+c+a+c
a + c + b = b + c + a 相遇点即为交点c开头
a1->a2->c1->c2->c3 A链结束接B链 ->b1->b2->b3->c1->c2->c3
b1->b2->b3->c1->c2->c3 B链结束接A链 ->a1->a2->c1->c2->c3
||
intersection
java
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA, b = headB;
while (a != b) {
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
}
161. One Edit Distance
https://leetcode.com/problems/one-edit-distance/description/
The "One Edit Distance" problem requires determining whether two given strings are exactly one edit apart. An edit can be one of the following:
Insert a single character into one string.
Delete a single character from one string.
Replace a single character in one string with another character.
Compare with length, if difference is large than 1 false
if str1 and str2 are same length, check if there is only one char difference
If not, if str1 > str 2, need to delete one in str1
else need to add one in str1
for(char c: str.toCharArray()){
if match continue, if not match if(str1 > str 2) str1 index ++
else str2 index++
}
public String substring(int begIndex);
java
public class Solution {
public boolean isOneEditDistance(String s, String t) {
int m = s.length();
int t = t.length();
// If length difference is more than 1, return false
if (Math.abs(m - t) > 1) {
return false;
}
// Iterate through both strings
for (int i = 0; i < Math.min(m, t); i++) {
if (s.charAt(i) != t.charAt(i)) {
// If strings are of same length, check for replace
if (m == t) {
return s.substring(i + 1).equals(t.substring(i + 1));
}
// If s is longer, check for delete in s
else if (m > t) {
return s.substring(i + 1).equals(t.substring(i));
}
// If t is longer, check for delete in t
else {
return s.substring(i).equals(t.substring(i + 1));
}
}
}
// If no mismatch was found, the strings are one edit apart
// if their lengths differ by exactly 1
return Math.abs(m - t) == 1;
}
}
162. Find Peak Element
A peak element is an element that is strictly greater than its neighbors.
Given a 0-indexed integer array nums, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks.
You may imagine that nums[-1] = nums[n] = -∞. In other words, an element is always considered to be strictly greater than a neighbor that is outside the array.
You must write an algorithm that runs in O(log n) time.
Binary Search
- nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1] : mid is the peak; return mid;
- nums[mid] < nums[mid-1]: end = mid -1
- nums[mid] > nums[mid-1]: -> nums[mid] > nums[mid+1] start = mid + 1
java
class Solution {
public int findPeakElement(int[] nums) {
if(nums.length == 1) return 0; // single element
int n = nums.length;
// check if 0th/n-1th index is the peak element
if(nums[0] > nums[1]) return 0;
if(nums[n-1] > nums[n-2]) return n-1;
// search in the remaining array
int start = 1;
int end = n-2;
while(start <= end) {
int mid = start + (end - start)/2;
if(nums[mid] > nums[mid-1] && nums[mid] > nums[mid+1]) return mid;
else if(nums[mid] < nums[mid-1]) end = mid - 1;
else if(nums[mid] < nums[mid+1]) start = mid + 1;
}
return -1; // dummy return statement
}
}
165. Compare Version Numbers
Given two version numbers, version1 and version2, compare them.
Version numbers consist of one or more revisions joined by a dot '.'. Each revision consists of digits and may contain leading zeros. Every revision contains at least one character. Revisions are 0-indexed from left to right, with the leftmost revision being revision 0, the next revision being revision 1, and so on. For example 2.5.33 and 0.1 are valid version numbers.
To compare version numbers, compare their revisions in left-to-right order. Revisions are compared using their integer value ignoring any leading zeros. This means that revisions 1 and 001 are considered equal. If a version number does not specify a revision at an index, then treat the revision as 0. For example, version 1.0 is less than version 1.1 because their revision 0s are the same, but their revision 1s are 0 and 1 respectively, and 0 < 1.
Return the following:
If version1 < version2, return -1.
If version1 > version2, return 1.
Otherwise, return 0.
Compare two String/list
java
while (i < a.length() && j < b.length()){ i++; j++; }
while(i < a.length()){ i++; }
while(j < b.length()){ j++; }
java
class Solution {
public int compareVersion(String version1, String version2) {
int i = 0,j = 0;
while(i < version1.length() && j < version2.length()){
int a = 0,b = 0;
while(i < version1.length() && version1.charAt(i)!='.'){
a *= 10;
a = a + version1.charAt(i) - '0';
i++;
}
while(j < version2.length() && version2.charAt(j)!='.'){
b *= 10;
b = b + version2.charAt(j) - '0';
j++;
}
if(a<b){
return -1;
} else if(a>b){
return 1;
}
i++;
j++;
}
while(i < version1.length()){
if(version1.charAt(i)-'0'>0){
return 1;
}
i++;
}
while(j < version2.length()){
if(version2.charAt(j)-'0'>0){
return -1;
}
j++;
}
return 0;
}
}
166. Fraction to Recurring Decimal
166. Fraction to Recurring Decimal
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
If multiple answers are possible, return any of them.
It is guaranteed that the length of the answer string is less than 104 for all the given inputs.
167. Two Sum II - Input Array Is Sorted
167. Two Sum II - Input Array Is Sorted
Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.
Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.
The tests are generated such that there is exactly one solution. You may not use the same element twice.
Your solution must use only constant extra space.
binary search/ two pointer/ begin , end
binary search:
- Array
- Number
- Sorted/ Order/ Partly order
- Find one number
java
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i=0,j=numbers.length-1;
while(i < j){
if(numbers[i] + numbers[j] == target)
return new int[]{i+1,j+1};
else if
(numbers[i] + numbers[j] < target)i++;
else
j--;
}
return new int[]{};
}
}
return new int[]{a,b};
168. Excel Sheet Column Title
Given an integer columnNumber, return its corresponding column title as it appears in an Excel sheet.
For example:
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
...
Input: columnNumber = 1
Output: "A"
System of numeration: 10 decimal system, 2 binary system, 8 octal system, 16 hexadecimal system
java
while(num>0){
remainder = num % s;
num = num / s; //s = 26
}
java
class Solution {
public String convertToTitle(int columnNumber) {
StringBuffer ans = new StringBuffer();
int temp;
while(columnNumber>0){
//1-26 remainder
columnNumber--;
temp = columnNumber%26;
ans.append((char)(temp+'A'));
columnNumber /=26;
}
return ans.reverse().toString();
}
}
169. Majority Element
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Follow-up: Could you solve the problem in linear time and in O(1) space?
Sorting
java
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
int i;
int count = 1;
int n = nums.length/2;
for(i = 0; i < nums.length-2; i++){
while(nums[i]==nums[i+1] && i < nums.length-2){
i++;
count++;
if(count>n) return nums[i];
}
if(nums[i]!=nums[i+1]){
count=1;
}
}
return nums[nums.length-1];
}
}
java
public int majorityElement1(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
171. Excel Sheet Column Number
171. Excel Sheet Column Number
Given a string columnTitle that represents the column title as appears in an Excel sheet, return its corresponding column number.
For example:
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
...
Example 1:
Input: columnTitle = "A"
Output: 1
from left to right
java
while(){
a *= n; //26
a += x; //1-26
}
java
class Solution {
public int titleToNumber(String columnTitle) {
int ans = 0;
int i;
for(i = 0; i < columnTitle.length(); i++){
ans *= 26;
ans = ans+columnTitle.charAt(i)-'A'+1;
}
return ans;
}
}
172. Factorial Trailing Zeroes
172. Factorial Trailing Zeroes
Given an integer n, return the number of trailing zeroes in n!.
Note that n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1.
Count factor 2 and 5. Trailing zeros are produce by 2 * 5 only.
count2[n] : how many factor 2 n process.
java
public int trailingZeroes(int n) {
//2*5 = 10
if(n<=4){
return 0;
}
int[] count2 = new int[n+1];
int[] count5 = new int[n+1];
int c2 = 0;
int c5 = 0;
count2[2] = 1;
count5[5] = 1;
for(int i = 1; i <= n; i++){
if(i%2==0){
count2[i] = 1 + (count2[i/2]);
c2 += count2[i];
}
if(i%5==0){
count5[i] = 1 + (count5[i/5]);
c5 += count5[i];
}
}
if(c2 > 0 && c5 > 0){
return Math.min(c2,c5);
}
return 0;
}
}
173. Binary Search Tree Iterator
173. Binary Search Tree Iterator
Implement the BSTIterator class that represents an iterator over the in-order traversal of a binary search tree (BST):
BSTIterator(TreeNode root) Initializes an object of the BSTIterator class. The root of the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST.
boolean hasNext() Returns true if there exists a number in the traversal to the right of the pointer, otherwise returns false.
int next() Moves the pointer to the right, then returns the number at the pointer.
Notice that by initializing the pointer to a non-existent smallest number, the first call to next() will return the smallest element in the BST.
You may assume that next() calls will always be valid. That is, there will be at least a next number in the in-order traversal when next() is called.
179. Largest Number
Given a list of non-negative integers nums, arrange them such that they form the largest number and return it.
Since the result may be very large, so you need to return a string instead of an integer.
Constraints:1 <= nums.length <= 100
0 <= nums[i] <= 109
Costom compare and sort the array.
The implementation of the compare() method should return
- a negative integer, if the first argument is less than the second,
- zero, if the first argument is equal to the second, and
- a positive integer, if the first argument is greater than the second.
Greedy
3、4、30 : 43 > 34 > 30
Method 2:
Compare with the String. s1 = a + b, s2 = b + a;
Costom compare
java
class Solution {
public String largestNumber(int[] nums) {
StringBuffer sb = new StringBuffer();
String[] arr = new String[nums.length];
for(int i = 0; i < nums.length; i++){
arr[i] = nums[i] +"";
}
Arrays.sort(arr,(a,b)->{
String s1 = a + b;
String s2 = b + a;
return s2.compareTo(s1);
});
for(String n:arr){
sb.append(n);
}
if(sb.charAt(0)=='0'){
return "0";
}
return sb.toString();
}
}
5ms 99.03% 41.9% 89.78%
custom sort / compare
- compareTo()
The compareTo() method compares two strings lexicographically .
The comparison is based on the Unicode value of each character in the strings.
Returns: An int value:
- 0 if the string is equal to the other string.
- < 0 if the string is lexicographically less than the other string
- > 0 if the string is lexicographically greater than the other string (more characters)
override the comparator
Comparison with Lambda
java
Arrays.sort(arr,(a,b)->{
String s1 = a + b;
String s2 = b + a;
return s2.compareTo(s1);
});
Override the comparator classic
java
Arrays.sort(temp, new Comparator<String>(){
@Override
public int compare(String a, String b) {
String s1 = a + b;
String s2 = b + a;
return s2.compareTo(s1);
}
});
Override the comparator
java
// Comparator to decide which string should come first in concatenation
Comparator<String> comp = new Comparator<String>(){
@Override
public int compare(String str1, String str2){
String s1 = str1 + str2;
String s2 = str2 + str1;
return s2.compareTo(s1); // reverse order here, so we can do append() later
}
};
Arrays.sort(s_num, comp);
As we know, there are basically two types of sorting technique in Java:
-
First is internal sorting i.e that uses predefined sorting method ascending order Arrays.sort() and Collections.sort() . Both methods sort the elements in ascending order.
-
The second technique is for sorting the elements is using the comparator or comparable interface in a class .
Comparator Interface: Implement the comparator interface in the class and override compare() method or pass the new comparator as the second argument in the sorting methods and change the sorting order according to the requirements. Comparator only works for wrapper type arrays and for collections like vector, ArrayList, etc.
Comparable Interface: This interface implements a single sorting technique, and it affects the whole class. The comparable interface provides a compareTo() method to sort the elements. Overriding of the compareTo() Method.
Sort array in the descending order
java
Arrays.sort(arr, Collections.reverseOrder());
187. Repeated DNA Sequences
The DNA sequence is composed of a series of nucleotides abbreviated as 'A', 'C', 'G', and 'T'.
For example, "ACGAATTCCG" is a DNA sequence.
When studying DNA, it is useful to identify repeated sequences within the DNA.
Given a string s that represents a DNA sequence, return all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule. You may return the answer in any order.
Example 1:Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
Output: ["AAAAACCCCC","CCCCCAAAAA"]
Example 2:
Input: s = "AAAAAAAAAAAAA"
Output: ["AAAAAAAAAA"]
Constraints:1 <= s.length <= 105
s[i] is either 'A', 'C', 'G', or 'T'.
Find a particular Sequence in String : Sliding window [ left, right ]
Check every 10-length substring. Add to the HashSet and check.
One Loop. O(n).
Check whether current subsequence is existed in the set.
If true, add it to the result. Else, add it to the set.
java
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
int right = 10,left = 0;
List<String> ansList = new ArrayList<>();
if(s.length() < 11){
return ansList;
}
HashSet<String> set = new HashSet<>();
set.add(s.substring(left,right));
right++;
left++;
while(right <= s.length()){
String ans = s.substring(left,right);
if(set.contains(ans)){
if(!ansList.contains(ans)){
//skip duplicate answer
ansList.add(ans);
}
}else{
set.add(ans);
}
left++;
right++;
}
return ansList;
}
}
17ms 89.51% 50.9MB 86.25%
Time Limit Exceeded
For every 10-length sequence check whether is duplicate by followed substring. If true, add it to the set. Return the set convert to list.
Has a lot of repetition. Check with nested loop. O(n^2)
java
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
int right = 10,left = 0;
List<String> ansList = new ArrayList<>();
if(s.length() < 11){
return ansList;
}
HashSet<String> set = new HashSet<>();
while(right <= s.length()){
int i = 1;
while(right + i<= s.length()){
if(s.substring(left,right).equals(s.substring(left+i,right+i))){
String ans = s.substring(left,right);
if(!set.contains(ans)){
ansList.add(ans);
set.add(ans);
}
break;
}
else{
i++;
}
}
left++;
right++;
}
return ansList;
}
}
189. Rotate Array
Given an array, rotate the array to the right by k steps, where k is non-negative.
Input: nums = [1,2,3,4,5,6,7], k = 3Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Try to come up with as many solutions as you can. There are at least three different ways to solve this problem.Could you do it in-place with O(1) extra space?
Swap the array
WIth extra space: Move the element to it defined location. -> Build a k-size storage space Store before you move
WIthout extra space: Divide the array into two part, these two parts change their position as a whole.
-> Reverse
1 2 3 4 5 6 7
Reverse the front len-k element: 4 3 2 1 | 5 6 7 |
Reverse the back k element: 4 3 2 1 | 7 6 5
Reverse all: 5 6 7 1 2 3 4
java
class Solution {
public void rotate(int[] nums, int k) {
//if(i+k<len) i->i+k else i->i+k-len
if(nums.length==1){
return;
}
if(k>nums.length){
k = k % nums.length;
}
reverse(nums,0,nums.length-k-1);
reverse(nums,nums.length-k,nums.length-1);
reverse(nums,0,nums.length-1);
}
//i end-start-i
private void reverse(int[] arr,int start,int end){
int temp;
int i = start,j = end;
while(i<j){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
}
1ms 89.73% 58.2MB 85.97%
190. Reverse Bits
Reverse bits of a given 32 bits unsigned integer.
Example 1:Input: n = 00000010100101000001111010011100
Output: 964176192 (00111001011110000010100101000000)
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.
Example 2:
Input: n = 11111111111111111111111111111101
Output: 3221225471 (10111111111111111111111111111111)
Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10111111111111111111111111111111.
Constraints:The input must be a binary string of length 32
Bitwise operation
Integer.parseInt();
Integer.parseUnsignedInt();
java
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
StringBuilder sb = new StringBuilder();
int count = 32;
while(count > 0){
sb.append((n&1));
n >>= 1;
count--;
}
return Integer.parseUnsignedInt(sb.toString(),2);
}
}
1 ms 97.06% 42.1 MB 68.24%
StringBuilder is faster than StringBuffer but it is thread unsafe.
- Integer.parseInt();
This method is used to get the primitive data type of a certain String. parseXxx() is a static method and can have one argument or two.
Syntax
- static int parseInt(String s)
- static int parseInt(String s, int radix)
Parameters
- s − This is a string representation of decimal.
- radix − This would be used to convert String s into integer. (10, 2, 8, or 16)
Return Value
parseInt(String s) − This returns an integer (decimal only).
parseInt(String s, int i) − This returns an integer, given a string representation of decimal, binary, octal, or hexadecimal (radix equals 10, 2, 8, or 16 respectively) numbers as input.
- Integer.parseUnsignedInt();
- Java Integer parseUnsignedInt (String s) Method
- Java Integer parseUnsignedInt (String s, int radix) Method
- Java Integer parseUnsignedInt (CharSequence s, int beginText, int endText, int radix) Method
java
//Notes
public class Solution {
// you need treat n as an unsigned value
/*
1. &按位与 两个为真才为真 1&1=1 , 1&0=0 , 0&1=0 , 0&0=0
2. | 按位或 一个为真即为真 1|0 = 1 , 1|1 = 1 , 0|0 = 0 , 0|1 = 1
3. ^ 异或运算符 1^0 = 1 , 1^1 = 0 , 0^1 = 1 , 0^0 = 0
4. <<左移运算符
5<<2的意思为5的二进制位往左挪两位,右边补0,5的二进制位是0000 0101 , 就是把有效值101往左挪两位就是0001 0100 ,正数左边第一位补0,负数补1,等于乘于2的n次方
5. >>右移运算符
凡位运算符都是把值先转换成二进制再进行后续的处理,5的二进制位是0000 0101,右移两位就是把101左移后为0000 0001,正数左边第一位补0,负数补1,等于除于2的n次方,结果为1
6. ~ 取反运算符
取反就是1为0,0为1,5的二进制位是0000 0101,取反后为1111 1010,值为-6
7. >>>无符号右移运算符
*/
public int reverseBits(int num) {
int ans = 0;
for(int i = 0; i < 32; i++){
ans <<= 1;//左移让出一位新的空间,并且使先加进去的到最前面,实现翻转
ans += (num>>i)&1;
//1只有一位所以的num的最右位与1与,通过>>i,随i增大,逐渐从右到左访问num的每一位
}
return ans;
}
1 ms 97.06% 41.5 MB 90.73%
191. Number of 1 Bits
Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight).
Example 1:Input: n = 00000000000000000000000000001011
Output: 3
Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.
Example 2:
Input: n = 00000000000000000000000010000000
Output: 1
Explanation: The input binary string 00000000000000000000000010000000 has a total of one '1' bit.
Example 3:
Input: n = 11111111111111111111111111111101
Output: 31
Explanation: The input binary string 11111111111111111111111111111101 has a total of thirty one '1' bits.
Constraints:The input must be a binary string of length 32.
Follow up: If this function is called many times, how would you optimize it?
bitwise & 1
Wrong. Can't use n > 0 as the loop condition, because the most signification bit is sign bit.
A positive integer starts with a 0, while a negative integer starts with a 1.
java
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
while(n > 0){
count += (n&1);
n >>= 1;
}
return count;
}
}
Input 11111111111111111111111111111101
Output 0
Expected 31
Your input 10000000000000000000000000000000Output 0
Expected 1
AC
Control 32 times >>
java
public class Solution {
// you need to treat n as an unsigned value
//右移>>是指带符号右移,如果最高位的符号位为1,则右移时左侧补上的空位用1填充,否则用0填充
//而无符号右移>>>,不管左侧最高位是1还是0,左侧补上的空位统统用0填充
public int hammingWeight(int n) {
int ans = 0;
for(int i = 0; i < 32; i++){
if(((n>>i)&1)==1){
ans++;
}
}
return ans;
}
}
java
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
int num = 32;
while(num > 0){
count += (n&1);
n >>= 1;
num--;
}
return count;
}
}
Name of operator | Sign | Description |
---|---|---|
Signed Right Shift | >> | The right shift operator moves all bits by a given number of bits to the right. Doesn't change the sign bit. |
Signed Left Shift | << | The left shift operator moves all bits by a given number of bits to the left. Doesn't change the sign bit. |
Unsigned Right Shift | >>> | It is the same as the signed right shift, but the vacant leftmost position is filled with 0 instead of the sign bit |
198. House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
Example 1:Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
Constraints:1 <= nums.length <= 100
0 <= nums[i] <= 400
DP
for the current house, there are two choices: rob or not
- rob : dp[ i ] = nums[ i ] + dp[ i - 2 ]
- not rob : dp[ i ] = dp[ i -1 ]
dp[ i ] = max (nums[ i ] + dp[ i - 2 ] , dp[ i -1 ])
java
class Solution {
public int rob(int[] nums) {
//can't rob adjacent house
if(nums.length == 1) return nums[0];
if(nums.length == 2) return Math.max(nums[0],nums[1]);
int[] note = new int[nums.length];
note[0] = nums[0];
note[1] = Math.max(nums[0],nums[1]);
//rob this house or rob former house
for(int i = 2; i < nums.length; i++){
note[i] = Math.max(note[i-2]+nums[i],note[i-1]);
}
return note[nums.length-1];
}
}
0ms 100% 39.7MB 66.74%
199. Binary Tree Right Side View
199. Binary Tree Right Side View
Given the root of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
Example 1:Input: root = [1,2,3,null,5,null,4]
Output: [1,3,4]
Example 2:
Input: root = [1,null,3]
Output: [1,3]
Example 3:
Input: root = []
Output: []
Constraints:The number of nodes in the tree is in the range [0, 100].
-100 <= Node.val <= 100
BFS level travese + read the last node in each level
java
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Queue<TreeNode> q = new LinkedList<>();
TreeNode p = root;
if(root == null){
return ans;
}
q.offer(root);
while(!q.isEmpty()){
int size = q.size();
for(int i = 0; i < size; i++){
p = q.peek();
q.poll();
if(p.left!=null)
q.offer(p.left);
if(p.right!=null)
q.offer(p.right);
}
ans.add(p.val);
}
return ans;
}
}
1 ms 90.33% 41.1 MB 81.46%
Queue in Java
Interface Queue< E >
All Superinterfaces:
Collection< E >, Iterable< E >
All Known Implementing Classes:
AbstractQueue, ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedList, LinkedTransferQueue, PriorityBlockingQueue, PriorityQueue, SynchronousQueue
Summary of Queue methods
Throws exception | Returns special value | |
---|---|---|
Insert | add(e) | offer(e) |
Remove | remove() | poll() |
Examine | element() | peek() |
The offer method inserts an element if possible, otherwise returning false. This differs from the Collection.add method, which can fail to add an element only by throwing an unchecked exception. The offer method is designed for use when failure is a normal, rather than exceptional occurrence, for example, in fixed-capacity (or "bounded") queues.
The remove() and poll() methods remove and return the head of the queue. Exactly which element is removed from the queue is a function of the queue's ordering policy, which differs from implementation to implementation. The remove() and poll() methods differ only in their behavior when the queue is empty: the remove() method throws an exception, while the poll() method returns null.
The element() and peek() methods return, but do not remove, the head of the queue.
200. Number of Islands
Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:Input: grid = [
"1","1","1","1","0"\], \["1","1","0","1","0"\], \["1","1","0","0","0"\], \["0","0","0","0","0"
]
Output: 1
Example 2:
Input: grid = [
"1","1","0","0","0"\], \["1","1","0","0","0"\], \["0","0","1","0","0"\], \["0","0","0","1","1"
]
Output: 3
Constraints:m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] is '0' or '1'.
DFS Traverse every node, if it is in a island. Traverse the island by search every four direction and mark after visiting. Traverse the whole grid and can get how many land are there.
visit land, count, change land into water
No need to use the extra visited array. Change the '1' into '0' in place. Use the given grid to mark the visited.
int[][] directions = {{0,1},{1,0},{0,-1},{-1,0}};
java
class Solution {
public int numIslands(char[][] grid) {
//DFS See how many connected domains there are. Once you find a connected domain, set it as visited
int ans = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j]=='1'){
dfs(grid,i,j);
ans++;
}
}
}
return ans;
}
private void dfs(char[][] grid,int x,int y){
grid[x][y] = '0';
// java Two-dimensional arrays {{},{}}
int[][] turn = {{0,1},{1,0},{0,-1},{-1,0}};
int dx,dy;
for(int i = 0; i < 4; i++){
dx = x + turn[i][0];
dy = y + turn[i][1];
if(dx >= 0 && dy >= 0 && dx < grid.length && dy < grid[0].length && grid[dx][dy]=='1'){
dfs(grid,dx,dy);
}
}
}
}
6 ms 62.81% 52.1 MB 71.29%
对于你的 DFS 解法,时间复杂度分析如下:
遍历网格:外层双重循环遍历了整个网格,每个元素只被访问一次,因此遍历网格的时间复杂度是 O(M×N),其中 M 和 N 分别是网格的行数和列数。
DFS 递归:在最坏情况下,每次 dfs 调用都可能遍历一个完整的岛屿区域,每个元素也只会被访问一次。因此 DFS 的每次调用最多也是 O(M×N),不过由于每个元素只访问一次,整体的时间复杂度仍然是 O(M×N)。
因此,DFS 解法的总体时间复杂度是 O(M×N)。
Method Easy to remeber
java
class Solution {
public int numIslands(char[][] grid) {
int count=0;
for(int i=0;i<grid.length;i++)
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]=='1'){
dfsFill(grid,i,j);
count++;
}
}
return count;
}
private void dfsFill(char[][] grid,int i, int j){
if(i>=0 && j>=0 && i<grid.length && j<grid[0].length&&grid[i][j]=='1'){
grid[i][j]='0';
dfsFill(grid, i + 1, j);
dfsFill(grid, i - 1, j);
dfsFill(grid, i, j + 1);
dfsFill(grid, i, j - 1);
}
}
}
4 ms 80.84% 58 MB 17.83%
Method Easy to remeber
java
class Solution {
public int numIslands(char[][] grid) {
int ans = 0;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j]=='1'){
dfs(grid,i,j);
ans++;
}
}
}
return ans;
}
private void dfs(char[][] grid,int x,int y){
grid[x][y] = '0';
if(x+1>=0 && x+1<grid.length &&grid[x+1][y]=='1'){
dfs(grid,x+1,y);
}
if(x-1>=0 && x-1<grid.length &&grid[x-1][y]=='1'){
dfs(grid,x-1,y);
}
if(y+1>=0 && y+1<grid[0].length &&grid[x][y+1]=='1'){
dfs(grid,x,y+1);
}
if(y-1>=0 && y-1<grid[0].length &&grid[x][y-1]=='1'){
dfs(grid,x,y-1);
}
}
}
4 ms 80.84% 57.8 MB 26.58%
Union Find
将网格中的每个陆地 1 看作是并查集中的一个节点,并且将相邻的陆地进行合并。在最终的并查集中,连通分量的数量就是岛屿的数量。
并查集解法的步骤
初始化并查集:为每个陆地 1 初始化一个独立的集合。
遍历网格:对于每一个陆地,如果其上下左右存在陆地,则将它们合并到同一个集合中。
统计岛屿数量:最终统计并查集中不同连通分量的数量,这个数量就是岛屿的数量。