\chapter{String}
\section{Reverse String} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Write a function that takes a string as input and returns the string reversed.
\textbf{Example:}
Given s = \code{"hello"}, return \code{"olleh"}.
\subsubsection{Solution}
\begin{Code}
public String reverseString(String s) {
return new StringBuilder(s).reverse().toString();
}
\end{Code}
\newpage
\section{Reverse String II} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string and an integer k, you need to reverse the first k characters for every 2k characters counting from the start of the string. If there are less than k characters left, reverse all of them. If there are less than 2k but greater than or equal to k characters, then reverse the first k characters and left the other as original.
\textbf{Example:}
\textbf{Input:} s = \code{"abcdefg"}, k = 2
\textbf{Output:} \code{"bacdfeg"}
\textbf{Restrictions:}
The string consists of lower English letters only.
Length of the given string and k will in the range \code{[1, 10000]}
\subsubsection{Solution}
\begin{Code}
public String reverseStr(String s, int k) {
if (s.length() <= k) {
return new StringBuilder(s).reverse().toString();
}
if (s.length() <= 2 * k) {
return reverseStr(s.substring(0, k), k) + s.substring(k);
}
return reverseStr(s.substring(0, 2 * k), k) + reverseStr(s.substring(2 * k), k);
}
\end{Code}
\newpage
\section{Reverse Words in a String} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an input string, reverse the string word by word.
For example,
Given s = "the sky is blue",
return "blue is sky the".
Clarification:
1. What constitutes a word?
A sequence of non-space characters constitutes a word.
2. Could the input string contain leading or trailing spaces?
Yes. However, your reversed string should not contain leading or trailing spaces.
3. How about multiple spaces between two words?
Reduce them to a single space in the reversed string.
\subsubsection{Solution I}
\begin{Code}
// èæ¶10ms
public String reverseWords(String s) {
StringBuilder sb = new StringBuilder();
boolean inWord = false;
char[] cc = s.toCharArray();
for (int i = cc.length - 1, idx = 0; i >= 0; i--) {
if (cc[i] != ' ') {
if (!inWord && sb.length() > 0) {
sb.append(' ');
}
inWord = true;
sb.insert(idx, cc[i]);
} else if (inWord) {
idx = sb.length() + 1;
inWord = false;
}
}
return sb.toString();
}
\end{Code}
\newpage
\subsubsection{Solution II}
\begin{Code}
// èæ¶18ms
public String reverseWords2(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0, j = 0; i < s.length(); ) {
if (s.charAt(i) == ' ') {
i++;
j = i;
} else if (j >= s.length() || s.charAt(j) == ' ') {
sb.insert(0, s.substring(i, j) + " ");
i = j;
} else {
j++;
}
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
\end{Code}
\newpage
\section{Reverse Words in a String II} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters.
The input string does not contain leading or trailing spaces and the words are always separated by a single space.
For example,
Given s = \code{"the sky is blue"},
return \code{"blue is sky the"}.
Could you do it in-place without allocating extra space?
\subsubsection{Solution}
\begin{Code}
public void reverseWords(char[] s) {
for (int i = 0, j = i; i < s.length; ) {
if (j >= s.length || s[j] == ' ') {
reverse(s, i, j - 1);
for (i = j; j < s.length && s[j] == ' '; j++, i = j) ;
} else {
j++;
}
}
reverse(s, 0, s.length - 1);
}
private void reverse(char[] s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
char t = s[i];
s[i] = s[j];
s[j] = t;
}
}
\end{Code}
\newpage
\section{Reverse Words in a String III} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order.
\textbf{Example 1:}
\textbf{Input:} \code{"Let's take LeetCode contest"}
\textbf{Output:} \code{"s'teL ekat edoCteeL tsetnoc"}
\textbf{Note:} In the string, each word is separated by single space and there will not be any extra space in the string.
\subsubsection{Solution}
\begin{Code}
public String reverseWords(String s) {
String[] texts = s.split(" ");
StringBuilder sb = new StringBuilder();
for (String text : texts) {
if (text.length() > 0) {
sb.append(new StringBuilder(text).reverse().toString()).append(" ");
}
}
return sb.toString().trim();
}
\end{Code}
\newpage
\section{Reverse Vowels of a String} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Write a function that takes a string as input and reverse only the vowels of a string.
\textbf{Example 1:}
Given s = \code{"hello"}, return \code{"holle"}.
\textbf{Example 2:}
Given s = \code{"leetcode"}, return \code{"leotcede"}.
\textbf{Note:}
The vowels does not include the letter \code{"y"}.
\subsubsection{Solution}
\begin{Code}
public String reverseVowels(String s) {
boolean[] flag = new boolean[256];
for (char c : "aeiouAEIOU".toCharArray()) {
flag[c] = true;
}
StringBuilder sb = new StringBuilder(s);
for (int i = 0, j = sb.length() - 1; i < j; ) {
if (!flag[sb.charAt(i)]) {
i++;
} else if (!flag[sb.charAt(j)]) {
j--;
} else {
char c = sb.charAt(i);
sb.setCharAt(i, sb.charAt(j));
sb.setCharAt(j, c);
i++;
j--;
}
}
return sb.toString();
}
\end{Code}
\newpage
\section{Longest Substring Without Repeating Characters} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, find the length of the longest substring without repeating characters.
\textbf{Examples:}
Given \code{"abcabcbb"}, the answer is \code{"abc"}, which the length is 3.
Given \code{"bbbbb"}, the answer is \code{"b"}, with the length of 1.
Given \code{"pwwkew"}, the answer is \code{"wke"}, with the length of 3. Note that the answer must be a substring, \code{"pwke"} is a subsequence and not a substring.
\subsubsection{Solution}
\begin{Code}
// èæ¶39msï¼æ§è½æºå¥½
public int lengthOfLongestSubstring(String s) {
int[] count = new int[256];
int maxLen = 0;
for (int i = 0, j = 0; j < s.length(); ) {
if (count[s.charAt(j)] == 0) {
count[s.charAt(j)]++;
maxLen = Math.max(maxLen, j - i + 1);
j++;
} else {
--count[s.charAt(i++)];
}
}
return maxLen;
}
\end{Code}
\newpage
\section{Longest Substring with At Most Two Distinct Characters} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, find the length of the longest substring T that contains at most 2 distinct characters.
For example, Given s = \code{âecebaâ},
T is \code{"ece"} which its length is 3.
\subsubsection{Solution}
\begin{Code}
// 7ms
public int lengthOfLongestSubstringTwoDistinct2(String s) {
int[] count = new int[256];
int distinct = 0, longest = 0;
for (int i = 0, j = 0; j < s.length(); j++) {
if (count[s.charAt(j)]++ == 0) {
distinct++;
}
for ( ; i < j && distinct > 2; ) {
if (--count[s.charAt(i++)] == 0) {
--distinct;
}
}
longest = Math.max(longest, j - i + 1);
}
return longest;
}
\end{Code}
\newpage
\section{Longest Substring with At Most K Distinct Characters} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, find the length of the longest substring T that contains at most k distinct characters.
For example, Given s = \code{âecebaâ} and k = 2,
T is \code{"ece"} which its length is 3.
\subsubsection{Solution}
\begin{Code}
/**
* æè·¯è·Longest Substring With At Most Two Distinct Characters䏿 ·ï¼åªæ¯ç»2æ¹ækï¼
* è¦æ³¨ækçäº0æ¶è¿å0
*/
// èæ¶9ms
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if (k == 0) {
return 0;
}
int[] count = new int[256];
int distinct = 0, longest = 0;
for (int i = 0, j = 0; j < s.length(); j++) {
if (count[s.charAt(j)]++ == 0) {
distinct++;
}
for ( ; i < j && distinct > k; ) {
if (--count[s.charAt(i++)] == 0) {
--distinct;
}
}
longest = Math.max(longest, j - i + 1);
}
return longest;
}
\end{Code}
\newpage
\section{Minimum Window Substring} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S = \code{"ADOBECODEBANC"}
T = \code{"ABC"}
Minimum window is \code{"BANC"}.
\textbf{Note:}
If there is no such window in S that covers all characters in T, return the empty string \code{""}.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
\subsubsection{Solution}
\begin{Code}
// èæ¶8msï¼æ¶é´å¤æåº¦O(n)
public String minWindow(String s, String t) {
int[] sc = new int[256], tc = new int[256];
for (char c : t.toCharArray()) {
tc[c]++;
}
int minStart = 0, minLen = Integer.MAX_VALUE;
for (int i = 0, j = 0, k = 0; j < s.length(); j++) {
char c = s.charAt(j);
if (++sc[c] <= tc[c]) {
++k;
}
if (k == t.length()) {
for (; i < j; i++) {
char cc = s.charAt(i);
if (tc[cc] == 0) {
continue;
}
if (sc[cc] <= tc[cc]) {
break;
}
sc[cc]--;
}
if (j - i + 1 < minLen) {
minLen = j - i + 1;
minStart = i;
}
}
}
return minLen != Integer.MAX_VALUE ? s.substring(minStart, minStart + minLen) : "";
}
\end{Code}
\newpage
\section{Sliding Window Maximum} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
For example,
Given nums = \code{[1,3,-1,-3,5,3,6,7]}, and k = 3.
\begin{Code}
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
\end{Code}
Therefore, return the max sliding window as \code{[3,3,5,5,6,7]}.
\textbf{Note:}
You may assume k is always valid, ie: 1 ⤠k ⤠input array's size for non-empty array.
\textbf{Follow up:}
Could you solve it in linear time?
\subsubsection{Solution I}
\begin{Code}
// 注æPriorityQueueçremoveå¤æåº¦æ¯O(k)ï¼æä»¥æ¬é¢å¤æåº¦æ¯O(n*k)
// å¯ä»¥å°PriorityQueue转æTreeMapï¼å¤æåº¦ä¸ºO(n*lgk), èæ¶58ms
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 0) {
return new int[0];
}
Queue queue = new PriorityQueue(new Comparator() {
@Override
public int compare(Integer i1, Integer i2) {
return i2 - i1;
}
});
for (int i = 0; i < k; i++) {
queue.offer(nums[i]);
}
int[] result = new int[nums.length - k + 1];
result[0] = queue.peek();
for (int i = 1; i < result.length; i++) {
queue.remove(nums[i - 1]);
queue.offer(nums[i + k - 1]);
result[i] = queue.peek();
}
return result;
}
\end{Code}
\newpage
\subsubsection{Solution II}
\begin{Code}
// èæ¶23ms
// queueä¸åçæ¯ç´¢å¼
public int[] maxSlidingWindow2(int[] nums, int k) {
if (nums.length == 0) {
return new int[0];
}
Deque queue = new LinkedList();
int[] result = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
if (!queue.isEmpty() && queue.peek() <= i - k) {
queue.removeFirst();
}
while (!queue.isEmpty() && nums[queue.peekLast()] < nums[i]) {
queue.pollLast();
}
queue.offerLast(i);
if (i >= k - 1) {
result[i - k + 1] = nums[queue.peek()];
}
}
return result;
}
\end{Code}
\newpage
\section{Sliding Window Median} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.
\textbf{Examples:}
[2,3,4] , the median is 3
[2,3], the median is (2 + 3) / 2 = 2.5
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Your job is to output the median array for each window in the original array.
For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.
\begin{Code}
Window position Median
--------------- -----
[1 3 -1] -3 5 3 6 7 1
1 [3 -1 -3] 5 3 6 7 -1
1 3 [-1 -3 5] 3 6 7 -1
1 3 -1 [-3 5 3] 6 7 3
1 3 -1 -3 [5 3 6] 7 5
1 3 -1 -3 5 [3 6 7] 6
\end{Code}
Therefore, return the median sliding window as \code{[1,-1,-1,3,5,6]}.
\textbf{Note:}
You may assume k is always valid, ie: k is always smaller than input array's size for non-empty array.
\subsubsection{Solution}
\begin{Code}
public double[] medianSlidingWindow(int[] nums, int k) {
double[] res = new double[nums.length - k + 1];
TreeMap minHeap = new TreeMap();
TreeMap maxHeap = new TreeMap(Collections.reverseOrder());
int minHeapCap = k / 2; //smaller heap when k is odd.
int maxHeapCap = k - minHeapCap;
for (int i = 0; i < k; i++) {
maxHeap.put(nums[i], maxHeap.getOrDefault(nums[i], 0) + 1);
}
int[] minHeapSize = new int[]{0};
int[] maxHeapSize = new int[]{k};
for (int i = 0; i < minHeapCap; i++) {
move1Over(maxHeap, minHeap, maxHeapSize, minHeapSize);
}
res[0] = getMedian(maxHeap, minHeap, maxHeapSize, minHeapSize);
int resIdx = 1;
for (int i = 0; i < nums.length - k; i++) {
int addee = nums[i + k];
if (addee <= maxHeap.keySet().iterator().next()) {
add(addee, maxHeap, maxHeapSize);
} else {
add(addee, minHeap, minHeapSize);
}
int removee = nums[i];
if (removee <= maxHeap.keySet().iterator().next()) {
remove(removee, maxHeap, maxHeapSize);
} else {
remove(removee, minHeap, minHeapSize);
}
//rebalance
if (minHeapSize[0] > minHeapCap) {
move1Over(minHeap, maxHeap, minHeapSize, maxHeapSize);
} else if (minHeapSize[0] < minHeapCap) {
move1Over(maxHeap, minHeap, maxHeapSize, minHeapSize);
}
res[resIdx] = getMedian(maxHeap, minHeap, maxHeapSize, minHeapSize);
resIdx++;
}
return res;
}
public double getMedian(TreeMap bigHeap, TreeMap smallHeap, int[] bigHeapSize, int[] smallHeapSize) {
return bigHeapSize[0] > smallHeapSize[0] ? (double) bigHeap.keySet().iterator().next() : ((double) bigHeap.keySet().iterator().next() + (double) smallHeap.keySet().iterator().next()) / 2.0;
}
//move the top element of heap1 to heap2
public void move1Over(TreeMap heap1, TreeMap heap2, int[] heap1Size, int[] heap2Size) {
int peek = heap1.keySet().iterator().next();
add(peek, heap2, heap2Size);
remove(peek, heap1, heap1Size);
}
public void add(int val, TreeMap heap, int[] heapSize) {
heap.put(val, heap.getOrDefault(val, 0) + 1);
heapSize[0]++;
}
public void remove(int val, TreeMap heap, int[] heapSize) {
if (heap.put(val, heap.get(val) - 1) == 1) heap.remove(val);
heapSize[0]--;
}
\end{Code}
\newpage
\section{Longest Palindromic Substring} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
\textbf{Example:}
\textbf{Input:} \code{"babad"}
\textbf{Output:} \code{"bab"}
\textbf{Note:} \code{"aba"} is also a valid answer.
\textbf{Example:}
\textbf{Input:} \code{"cbbd"}
\textbf{Output:} \code{"bb"}
\subsubsection{Solution I}
\begin{Code}
private int begin, maxLen;
// èæ¶14msï¼å¹³åå¤æåº¦O(n)
public String longestPalindrome(String s) {
for (int i = 0; i < s.length(); i++) {
helper(s, i, i);
helper(s, i, i + 1);
}
return s.substring(begin, begin + maxLen);
}
private void helper(String s, int i, int j) {
for (; i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j); i--, j++) ;
int len = j - i - 1;
if (len > maxLen) {
maxLen = len;
begin = i + 1;
}
}
\end{Code}
\newpage
\subsubsection{Solution II}
\begin{Code}
// 卿è§åï¼èæ¶73msï¼å¤æåº¦O(n^2)
public String longestPalindrome2(String s) {
int len = s.length();
if (len == 0) {
return s;
}
boolean[][] f = new boolean[len][len];
int index = 0;
int max = 1;
for (int i = 0; i < len; i++) {
for (int j = 0; j <= i; j++) {
if (s.charAt(j) == s.charAt(i) && (i - j < 2 || f[j + 1][i - 1])) {
f[j][i] = true;
if (i - j + 1 > max) {
max = i - j + 1;
index = j;
}
}
}
}
return s.substring(index, index + max);
}
\end{Code}
\newpage
\section{Shortest Palindrome} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.
For example:
Given \code{"aacecaaa"}, return \code{"aaacecaaa"}.
Given \code{"abcd"}, return \code{"dcbabcd"}.
\subsubsection{Solution}
\begin{Code}
/**
* å
¶å®åªè¦å°sä¸sçéåºä¸²æ¼æ¥å¨ä¸èµ·ï¼æ±æé¿å
Œ
±å串ï¼éåºä¸²ä¸å¨é¤è¿ä¸ªæé¿å
Œ
±å串ï¼
* å°±æ¯è¦å å°såé¢ç
*/
public String shortestPalindrome(String s) {
StringBuilder builder = new StringBuilder(s);
return builder.reverse().substring(0, s.length() - getCommonLength(s)) + s;
}
private int getCommonLength(String str) {
StringBuilder builder = new StringBuilder(str);
String rev = new StringBuilder(str).reverse().toString();
builder.append("#").append(rev);
int[] p = new int[builder.length()];
for (int i = 1; i < p.length; i++) {
int j = p[i - 1];
while (j > 0 && builder.charAt(i) != builder.charAt(j)) j = p[j - 1];
p[i] = j == 0 ? (builder.charAt(i) == builder.charAt(0) ? 1 : 0) : j + 1;
}
return p[p.length - 1];
}
/**
* æ´ç´è§çåæ³
*/
private int getCommonLength2(String str) {
String rev = new StringBuilder(str).reverse().toString();
return getCommonLength(str + rev, str.length());
}
private int getCommonLength(String s, int max) {
for (int i = s.length() - max; i < s.length(); i++) {
if (s.startsWith(s.substring(i))) {
return s.length() - i;
}
}
return 0;
}
\end{Code}
\newpage
\section{Count and Say} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
The count-and-say sequence is the sequence of integers with the first five terms as following:
\begin{Code}
1. 1
2. 11
3. 21
4. 1211
5. 111221
\end{Code}
1 is read off as \code{"one 1"} or 11.
11 is read off as \code{"two 1s"} or 21.
21 is read off as \code{"one 2, then one 1"} or 1211.
Given an integer n, generate the nth term of the count-and-say sequence.
\textbf{Note:} Each term of the sequence of integers will be represented as a string.
\subsubsection{Solution}
\begin{Code}
public String countAndSay(int n) {
String s = "1";
for (int i = 2; i <= n; i++) {
s = next(s);
}
return s;
}
private String next(String s) {
StringBuilder sb = new StringBuilder();
char cur = 0;
int times = 0;
for (int i = 0; i < s.length(); i++) {
if (times == 0) {
cur = s.charAt(i);
times = 1;
} else if (s.charAt(i) == cur) {
times++;
} else {
sb.append(String.format("%d%c", times, cur));
cur = s.charAt(i);
times = 1;
}
}
// è¿ä¸å¥åä¸å«æäº
if (times != 0) {
sb.append(String.format("%d%c", times, cur));
}
return sb.toString();
}
\end{Code}
\newpage
\section{Valid Parentheses} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string containing just the characters \code{'(', ')', '{', '}', '[' and ']'}, determine if the input string is valid.
The brackets must close in the correct order, \code{"()"} and \code{"()[]{}"} are all valid but \code{"(]"} and \code{"([)]"} are not.
\subsubsection{Solution}
\begin{Code}
// èæ¶5ms
public boolean isValid(String s) {
char[] stack = new char[s.length()];
int top = -1;
for (char c : s.toCharArray()) {
switch (c) {
case ')':
if (top >= 0 && stack[top] == '(') {
top--;
} else {
return false;
}
break;
case '}':
if (top >= 0 && stack[top] == '{') {
top--;
} else {
return false;
}
break;
case ']':
if (top >= 0 && stack[top] == '[') {
top--;
} else {
return false;
}
break;
default:
stack[++top] = c;
break;
}
}
return top < 0;
}
\end{Code}
\newpage
\section{Group Anagrams} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an array of strings, group anagrams together.
For example, given: \code{["eat", "tea", "tan", "ate", "nat", "bat"]},
Return:
\begin{Code}
[
["ate", "eat","tea"],
["nat","tan"],
["bat"]
]
\end{Code}
\textbf{Note:} All inputs will be in lower-case.
\subsubsection{Solution}
\begin{Code}
public List> groupAnagrams(String[] strs) {
HashMap> map = new HashMap<>();
for (String s : strs) {
char[] cc = s.toCharArray();
Arrays.sort(cc);
String t = new String(cc);
List list = map.get(t);
if (list == null) {
list = new LinkedList<>();
map.put(t, list);
}
list.add(s);
}
return new LinkedList<>(map.values());
}
\end{Code}
\newpage
\section{Add Binary} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given two binary strings, return their sum (also a binary string).
For example,
a = \code{"11"}
b = \code{"1"}
Return \code{"100"}.
\subsubsection{Solution}
\begin{Code}
public String addBinary(String a, String b) {
StringBuilder sb = new StringBuilder();
int i = a.length() - 1, j = b.length() - 1, k = 0;
for ( ; i >= 0 || j >= 0 || k > 0; i--, j--) {
int i0 = i >= 0 ? a.charAt(i) - '0' : 0;
int j0 = j >= 0 ? b.charAt(j) - '0' : 0;
int s = i0 + j0 + k;
sb.insert(0, s & 1);
k = s >> 1;
}
return sb.toString();
}
\end{Code}
\newpage
\section{String to Integer (atoi)} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Implement atoi to convert a string to an integer.
\textbf{Hint:} Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
\textbf{Notes:} It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
\subsubsection{Analysis}
1. è¿æ»¤æåé¢çç©ºæ ¼
2. èèæ£è´å·
3. å¦ææº¢åºåè¿åä¸éæä¸é
4. è§£ææ¶éå°éæ³å符å忢ï¼è¿åå½åç»æ
5ï¼é²å¾¡ç©ºä¸²
\subsubsection{Solution}
\begin{Code}
public int myAtoi(String str) {
long n = 0, sign = 1;
str = str.trim();
// è¿éè¦é²å¾¡ç©ºä¸²
if (str.length() == 0) { return 0; }
switch (str.charAt(0)) {
case '-':
sign = -1;
case '+':
str = str.substring(1);
break;
}
for (char c : str.toCharArray()) {
if (c >= '0' && c <= '9') {
n = n * 10 + (c - '0');
if (n * sign > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
} else if (n * sign < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
} else {
break;
}
}
return (int) (n * sign);
}
\end{Code}
\newpage
\section{Implement strStr()} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
\subsubsection{Solution}
\begin{Code}
// è¿éé常éè¦çæ¯i<=len1-len2ï¼å¦ææ²¡æè¿ä¸ªä¼è¶
æ¶
public int strStr(String haystack, String needle) {
int l1 = haystack.length(), l2 = needle.length();
for (int i = 0, j; i + l2 - 1 < l1; i++) {
for (j = 0; j < l2; j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
break;
}
}
if (j >= l2) {
return i;
}
}
return -1;
}
\end{Code}
\newpage
\section{Integer to English Words} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1.
For example,
\begin{Code}
123 -> "One Hundred Twenty Three"
12345 -> "Twelve Thousand Three Hundred Forty Five"
1234567 -> "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"
\end{Code}
\subsubsection{Solution}
\begin{Code}
private final String[] LESS_20 = {
"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven",
"Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"
};
private final String[] LESS_100 = {
"", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
};
private final String[] THOUSANDS = {
"", "Thousand", "Million", "Billion"
};
/**
* 1, 嫿¼äºzeroçæ
åµ
* 2ï¼ å½num % 1000 != 0ç夿嫿äº
* 3ï¼ helperçè¿åç»æè¦trimä¸ä¸ï¼å»æååå¤ä½çç©ºæ ¼
* 4ï¼ æåè¿åçsbè¦trimä¸ä¸
*/
public String numberToWords(int num) {
if (num == 0) {
return "Zero";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < THOUSANDS.length && num > 0; i++) {
if (num % 1000 != 0) {
sb.insert(0, helper(num % 1000).trim() + " " + THOUSANDS[i] + " ");
}
num /= 1000;
}
return sb.toString().trim();
}
private String helper(int num) {
if (num < 20) {
return LESS_20[num];
} else if (num < 100) {
return LESS_100[num / 10] + " " + helper(num % 10);
} else {
return LESS_20[num / 100] + " Hundred " + helper(num % 100);
}
}
\end{Code}
\newpage
\section{Multiply Strings} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.
Note:
1. The length of both num1 and num2 is < 110.
2. Both num1 and num2 contains only digits 0-9.
3. Both num1 and num2 does not contain any leading zero.
4. You must not use any built-in BigInteger library or convert the inputs to integer directly.
\subsubsection{Solution}
\begin{Code}
public String multiply(String num1, String num2) {
int len1 = num1.length(), len2 = num2.length();
int[] result = new int[len1 + len2];
for (int i = len1 - 1; i >= 0; i--) {
for (int j = len2 - 1; j >= 0; j--) {
int res = result[i + j + 1] + (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
result[i + j + 1] = res % 10;
result[i + j] += res / 10;
}
}
StringBuilder sb = new StringBuilder();
for (int n : result) {
// è¿éè¦å»æå¤´é¨ç"0"
if (n == 0 && sb.length() == 0) {
continue;
}
sb.append(n);
}
/**
* è¿éè¦æ³¨æå¦ææ¯ç©ºè¦è¿å0
*/
return sb.length() == 0 ? "0" : sb.toString();
}
\end{Code}
\newpage
\section{Compare Version Numbers} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Compare two version numbers version1 and version2.
If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0.
You may assume that the version strings are non-empty and contain only digits and the \fn{.} character.
The \fn{.} character does not represent a decimal point and is used to separate number sequences.
For instance, 2.5 is not \code{"two and a half"} or \code{"half way to version three"}, it is the fifth second-level revision of the second first-level revision.
Here is an example of version numbers ordering:
\code{0.1 < 1.1 < 1.2 < 13.37}
\subsubsection{Solution}
\begin{Code}
\end{Code}
\newpage
\section{Palindrome Pairs} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome.
\textbf{Example 1:}
Given words = \code{["bat", "tab", "cat"]}
Return \code{[[0, 1], [1, 0]]}
The palindromes are \code{["battab", "tabbat"]}
\textbf{Example 2:}
Given words = \code{["abcd", "dcba", "lls", "s", "sssll"]}
Return \code{[[0, 1], [1, 0], [3, 2], [2, 4]]}
The palindromes are \code{["dcbaabcd", "abcddcba", "slls", "llssssll"]}
\subsubsection{Solution}
\begin{Code}
public List> palindromePairs(String[] words) {
List> result = new ArrayList>();
for (int i = 0; i < words.length - 1; i++) {
for (int j = i + 1; j < words.length; j++) {
if (isPalindromePair(words[i], words[j])) {
result.add(Arrays.asList(i, j));
}
if (isPalindromePair(words[j], words[i])) {
result.add(Arrays.asList(j, i));
}
}
}
return result;
}
private boolean isPalindromePair(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
for (int l = 0, r = len1 + len2 - 1; l < r; l++, r--) {
char c1 = l < len1 ? word1.charAt(l) : word2.charAt(l - len1);
char c2 = r < len1 ? word1.charAt(r) : word2.charAt(r - len1);
if (c1 != c2) {
return false;
}
}
return true;
}
\end{Code}
\newpage
\section{Valid Palindrome} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
For example,
\code{"A man, a plan, a canal: Panama"} is a palindrome.
\code{"race a car"} is not a palindrome.
\textbf{Note:}
Have you consider that the string might be empty? This is a good question to ask during an interview.
For the purpose of this problem, we define empty string as valid palindrome.
\subsubsection{Solution}
\begin{Code}
/**
* 空串认为æ¯true
*/
// èæ¶10ms
public boolean isPalindrome(String s) {
/**
* å 为æ¯å¿½ç¥å¤§å°åï¼æä»¥è¿éå
转åæå°å
*/
s = s.toLowerCase();
for (int i = 0, j = s.length() - 1; i < j; ) {
if (!Character.isLetterOrDigit(s.charAt(i))) {
i++;
} else if (!Character.isLetterOrDigit(s.charAt(j))) {
j--;
} else {
if (s.charAt(i) != s.charAt(j)) {
return false;
} else {
i++;
j--;
}
}
}
return true;
}
\end{Code}
\newpage
\section{Valid Number} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Validate if a given string is numeric.
Some examples:
\begin{Code}
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
\end{Code}
\textbf{Note:} It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
\subsubsection{Solution}
\begin{Code}
\end{Code}
\newpage
\section{Substring with Concatenation of All Words} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
For example, given:
\begin{Code}
s: "barfoothefoobarman"
words: ["foo", "bar"]
\end{Code}
You should return the indices: \code{[0,9]}.
(order does not matter).
\subsubsection{Solution}
\begin{Code}
// è¿äºwordså¯è½æéå¤
public List findSubstring(String s, String[] words) {
List list = new LinkedList<>();
if (words.length == 0 || s.length() == 0) {
return list;
}
int len = words[0].length();
int total = len * words.length;
if (s.length() < total) {
return list;
}
HashMap map = new HashMap<>();
for (String word : words) {
map.put(word, 1 + map.getOrDefault(word, 0));
}
for (int i = 0; i <= s.length() - total; ) {
if (isMatch(s, i, i + total, len, map)) {
list.add(i);
}
i++;
}
return list;
}
\end{Code}
\newpage
\begin{Code}
private boolean isMatch(String s, int start, int end, int len, HashMap map0) {
HashMap map = new HashMap<>(map0);
for (int i = start; i < end; i += len) {
String t = s.substring(i, i + len);
int m = map.getOrDefault(t, 0);
if (m > 1) {
map.put(t, m - 1);
} else if (m == 1) {
map.remove(t);
} else {
return false;
}
}
return map.isEmpty();
}
\end{Code}
\newpage
\section{Simplify Path} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an absolute path for a file (Unix-style), simplify it.
For example,
\begin{Code}
path = "/home/", => "/home"
path = "/a/./b/../../c/", => "/c"
\end{Code}
\textbf{Corner Cases:}
Did you consider the case where path = \code{"/../"}? In this case, you should return "/".
Another corner case is the path might contain multiple slashes \code{'/'} together, such as \code{"/home//foo/"}.
In this case, you should ignore redundant slashes and return \code{"/home/foo"}.
\subsubsection{Solution}
\begin{Code}
public String simplifyPath(String path) {
String[] ss = path.split("/");
/**
* 注æè¿éè¦ç¨å端éåï¼å 为åé¢è¦çæè·¯å¾éè¦ä»åå¾å
*/
Deque queue = new LinkedList<>();
for (String s : ss) {
/**
* 注æè¿é嫿äºs为空çæ
åµï¼æ¯å¦"//"æ¶sä¼ä¸ºç©º
*/
if (s.length() == 0 || s.equals(".")) {
continue;
}
if (s.equals("..")) {
if (!queue.isEmpty()) {
/**
* è¿éåä¸é¢é½å«ç¨stackæè
pushï¼å 为ä»ä»¬é½æ¯å¨å¤´é¨æä½èéå°¾é¨
*/
queue.pollLast();
}
} else {
queue.offerLast(s);
}
}
/**
* è¿éè¦æ³¨æqueueå¯è½ä¸ºç©ºï¼ä¸è¿å¥½å¨joinä¼è¿å空
*/
return "/" + String.join("/", queue);
}
\end{Code}
\newpage
\section{Text Justification} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.
You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters.
Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.
For the last line of text, it should be left justified and no extra space is inserted between words.
For example,
\begin{Code}
words: ["This", "is", "an", "example", "of", "text", "justification."]
L: 16.
\end{Code}
Return the formatted lines as:
\begin{Code}
[
"This is an",
"example of text",
"justification. "
]
\end{Code}
\textbf{Note:} Each word is guaranteed not to exceed L in length.
\textbf{Corner Cases:}
A line other than the last line might contain only one word. What should you do in this case? In this case, that line should be left-justified.
\subsubsection{Analysis}
è¿é¢æå 个æ¡ä»¶:
妿ä¸è¡åªæä¸ä¸ªåè¯æè
è¯¥è¡æ¯æåä¸è¡ï¼åå¾å·¦é
å
¶ä½æ
åµåå¾ä¸¤è¾¹ææ»¡ï¼ä¸é´åè¡¡å°å¡«å
ç©ºæ ¼ï¼å¦æä¸è½åè¡¡ï¼å左边ä¼å
\newpage
\subsubsection{Solution}
\begin{Code}
public List fullJustify(String[] words, int maxWidth) {
List result = new LinkedList();
int count, last;
for (int first = 0; first < words.length; first = last) {
for (last = first, count = 0; last < words.length; last++) {
if (count + words[last].length() + last - first > maxWidth) {
break;
}
count += words[last].length();
}
StringBuilder sb = new StringBuilder();
// æåä¸è¡æè
ä¸è¡åªæä¸ä¸ªåè¯çæ
åµ
if (last == words.length || last - first == 1) {
for (int i = first; i < last; i++) {
sb.append(words[i]).append(" ");
}
// è¿éç»æåçç©ºæ ¼å»ææ¯é¿å
æåçç©ºæ ¼å¯¼è´è¶
åº
sb.deleteCharAt(sb.length() - 1);
for ( ; sb.length() < maxWidth; sb.append(" "));
} else {
int spaces = maxWidth - count;
int avg = spaces / (last - first - 1);
int extraSpaces = spaces - avg * (last - first - 1);
for (int i = first; i < last; i++) {
sb.append(words[i]);
if (i < last - 1) { // 注æè¿é嫿äºï¼æåä¸ä¸ªåè¯åæ¯ä¸è·ç©ºæ ¼ç
int curSpaces = avg + (extraSpaces > 0 ? 1 : 0);
for (int j = 0; j < curSpaces; j++) {
sb.append(" ");
}
extraSpaces--;
}
}
}
result.add(sb.toString());
}
return result;
}
\end{Code}
\newpage
\section{Read N Characters Given Read4} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
\textbf{Note:}
The read function will only be called once for each test case.
\subsubsection{Solution}
\begin{Code}
public int read(char[] buf, int n) {
char[] tmp = new char[4];
int i = 0;
for ( ; i < n; i++) {
int size = read4(tmp);
for (int j = 0; j < size && i < n; ) {
buf[i++] = tmp[j++];
}
if (size < 4) {
break;
}
}
return i;
}
\end{Code}
\newpage
\section{Read N Characters Given Read4 II - Call multiple times} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
\textbf{Note:}
The read function may be called multiple times.
\subsubsection{Solution}
\begin{Code}
private char[] mTmp = new char[4];
private int mIndex = 0, mSize = 0;
public int read(char[] buf, int n) {
int i = 0;
for (; i < n; ) {
if (mIndex < mSize) {
buf[i++] = mTmp[mIndex++];
} else {
mIndex = 0;
mSize = read4(mTmp);
if (mSize <= 0) {
break;
}
}
}
return i;
}
\end{Code}
\newpage
\section{Group Shifted Strings} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a string, we can \code{"shift"} each of its letter to its successive letter, for example: \code{"abc" -> "bcd"}. We can keep \code{"shifting"} which forms the sequence:
\code{"abc" -> "bcd" -> ... -> "xyz"}
Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.
For example, given: \code{["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"]},
A solution is:
\begin{Code}
[
["abc","bcd","xyz"],
["az","ba"],
["acef"],
["a","z"]
]
\end{Code}
\subsubsection{Solution}
\begin{Code}
\end{Code}
\newpage
\section{Encode and Decode Strings} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.
Machine 1 (sender) has the function:
\begin{Code}
string encode(vector strs) {
// ... your code
return encoded_string;
}
\end{Code}
Machine 2 (receiver) has the function:
\begin{Code}
vector decode(string s) {
//... your code
return strs;
}
\end{Code}
So Machine 1 does:
\begin{Code}
string encoded_string = encode(strs);
\end{Code}
and Machine 2 does:
\begin{Code}
vector strs2 = decode(encoded_string);
\end{Code}
strs2 in Machine 2 should be the same as strs in Machine 1.
Implement the encode and decode methods.
\textbf{Note:}
The string may contain any possible characters out of 256 valid ascii characters. Your algorithm should be generalized enough to work on any possible characters.
Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
Do not rely on any library method such as eval or serialize methods. You should implement your own encode/decode algorithm.
\subsubsection{Solution}
\begin{Code}
public String encode(List strs) {
StringBuilder sb = new StringBuilder();
for (String str : strs) {
sb.append(str.length()).append("/").append(str);
}
return sb.toString();
}
public List decode(String s) {
List list = new LinkedList();
for (int i = 0; i < s.length(); ) {
int index = s.indexOf("/", i);
int size = Integer.parseInt(s.substring(i, index));
i = index + 1 + size;
list.add(s.substring(index + 1, i));
}
return list;
}
\end{Code}
\newpage
\section{Repeated Substring Pattern} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a non-empty string check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. You may assume the given string consists of lowercase English letters only and its length will not exceed 10000.
\textbf{Example 1:}
\textbf{Input:} \code{"abab"}
\textbf{Output:} True
\textbf{Explanation:} It's the substring \code{"ab"} twice.
\textbf{Example 2:}
\textbf{Input:} \code{"aba"}
\textbf{Output:} False
\textbf{Example 3:}
\textbf{Input:} \code{"abcabcabcabc"}
\textbf{Output:} True
\textbf{Explanation:} It's the substring \code{"abc"} four times. (And the substring \code{"abcabc"} twice.)
\subsubsection{Solution}
\begin{Code}
\end{Code}
\newpage
\section{Validate IP Address} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Write a function to check whether an input string is a valid IPv4 address or IPv6 address or neither.
IPv4 addresses are canonically represented in dot-decimal notation, which consists of four decimal numbers, each ranging from 0 to 255, separated by dots ("."), e.g.,172.16.254.1;
Besides, leading zeros in the IPv4 is invalid. For example, the address 172.16.254.01 is invalid.
IPv6 addresses are represented as eight groups of four hexadecimal digits, each group representing 16 bits. The groups are separated by colons (":"). For example, the address 2001:0db8:85a3:0000:0000:8a2e:0370:7334 is a valid one. Also, we could omit some leading zeros among four hexadecimal digits and some low-case characters in the address to upper-case ones, so 2001:db8:85a3:0:0:8A2E:0370:7334 is also a valid IPv6 address(Omit leading zeros and using upper cases).
However, we don't replace a consecutive group of zero value with a single empty group using two consecutive colons (::) to pursue simplicity. For example, 2001:0db8:85a3::8A2E:0370:7334 is an invalid IPv6 address.
Besides, extra leading zeros in the IPv6 is also invalid. For example, the address 02001:0db8:85a3:0000:0000:8a2e:0370:7334 is invalid.
Note: You may assume there is no extra space or special characters in the input string.
\textbf{Example 1:}
\textbf{Input:} \code{"172.16.254.1"}
\textbf{Output:} \code{"IPv4"}
\textbf{Explanation:} This is a valid IPv4 address, return \code{"IPv4"}.
\textbf{Example 2:}
\textbf{Input:} \code{"2001:0db8:85a3:0:0:8A2E:0370:7334"}
\textbf{Output:} \code{"IPv6"}
\textbf{Explanation:} This is a valid IPv6 address, return \code{"IPv6"}.
\textbf{Example 3:}
\textbf{Input:} \code{"256.256.256.256"}
\textbf{Output:} \code{"Neither"}
\textbf{Explanation:} This is neither a IPv4 address nor a IPv6 address.
\subsubsection{Solution}
\begin{Code}
\end{Code}
\newpage
\section{Valid Word Abbreviation} %%%%%%%%%%%%%%%%%%%%%%â¨â¨
\subsubsection{Description}
Given a non-empty string s and an abbreviation abbr, return whether the string matches with the given abbreviation.
A string such as \code{"word"} contains only the following valid abbreviations:
\code{["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"]}
Notice that only the above abbreviations are valid abbreviations of the string \code{"word"}. Any other string is not a valid abbreviation of \code{"word"}.
\textbf{Note:}
Assume s contains only lowercase letters and abbr contains only lowercase letters and digits.
\textbf{Example 1:}
Given s = \code{"internationalization"}, abbr = \code{"i12iz4n"}:
Return true.
\textbf{Example 2:}
Given s = \code{"apple"}, abbr = \code{"a2e"}:
Return false.
\subsubsection{Solution}
\begin{Code}
public boolean validWordAbbreviation(String word, String abbr) {
int i = 0, j = 0;
for (int value = 0; i < word.length() && j < abbr.length(); ) {
if (word.charAt(i) == abbr.charAt(j)) {
i++; j++;
continue;
}
if (abbr.charAt(j) <= '0' || abbr.charAt(j) > '9') {
return false;
}
for (value = 0; j < abbr.length() && abbr.charAt(j) >= '0' && abbr.charAt(j) <= '9'; j++) {
value = value * 10 + (abbr.charAt(j) - '0');
}
i += value;
}
return i == word.length() && j == abbr.length();
}
\end{Code}
\newpage