2. 尾部的零
描述
设计一个算法,计算出n阶乘中尾部零的个数
您在真实的面试中是否遇到过这个题? 是
样例
11! = 39916800,因此应该返回 2
挑战
O(logN)的时间复杂度
class Solution {
public:
/*
* @param n: A long integer
* @return: An integer, denote the number of trailing zeros in n!
*/
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
long count = 0;
long temp = n/5;
while(temp != 0){
count += temp;
temp /= 5;
}
return count;
}
};
6. 合并排序数组 II
描述
合并两个排序的整数数组A和B变成一个新的数组。
您在真实的面试中是否遇到过这个题? 是
样例
给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6]
挑战
你能否优化你的算法,如果其中一个数组很大而另一个数组很小?
class Solution {
public:
/**
* @param A: sorted integer array A
* @param B: sorted integer array B
* @return: A new sorted integer array
*/
vector<int> mergeSortedArray(vector<int> &A, vector<int> &B) {
// write your code here
int m = A.size(); int n = B.size();
vector<int> result;
int i = 0, j = 0;
while (i < A.size() && j < B.size()) {
if (A[i] < B[j]) {
result.push_back(A[i++]);
} else {
result.push_back(B[j++]);
}
}
while (i < A.size()) {
result.push_back(A[i++]);
}
while (j < B.size()) {
result.push_back(B[j++]);
}
return result;}
};
8. 旋转字符串
描述
给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转)
您在真实的面试中是否遇到过这个题? 是
样例
对于字符串 "abcdefg"
.
offset=0 => "abcdefg"
offset=1 => "gabcdef"
offset=2 => "fgabcde"
offset=3 => "efgabcd"
挑战
在数组上原地旋转,使用O(1)的额外空间
class Solution {
public:
/**
* @param str: a string
* @param offset: an integer
* @return: nothing
*/
void reverseString(string& str, int start, int end) {
while(start < end) {
char tmp = str[start];
str[start] = str[end];
str[end] = tmp;
++start;
--end;
}
}
void rotateString(string &str,int offset){
//wirte your code here
if(offset < 0 || str.empty())
return;
int len = (int)str.length();
offset = len - offset % len;
reverseString(str, 0, offset-1);
reverseString(str, offset, len-1);
reverseString(str, 0 , len-1);
}
};
9. Fizz Buzz 问题
描述
给你一个整数n. 从 1 到 n 按照下面的规则打印每个数:
- 如果这个数被3整除,打印
fizz
. - 如果这个数被5整除,打印
buzz
. - 如果这个数能同时被
3
和5
整除,打印fizz buzz
.
您在真实的面试中是否遇到过这个题? 是
样例
比如 n = 15
, 返回一个字符串数组:
[
"1", "2", "fizz",
"4", "buzz", "fizz",
"7", "8", "fizz",
"buzz", "11", "fizz",
"13", "14", "fizz buzz"
]
挑战
Can you do it with only one if
statement?
class Solution {
public:
/**
* @param n: An integer
* @return: A list of strings.
*/
vector<string> fizzBuzz(int n) {
// write your code here
vector<string> result;
for(int i = 1; i<=n ; i++)
{
if(i%15 == 0)
result.push_back("fizz buzz");
else if(i%5 == 0)
result.push_back("buzz");
else if(i%3 == 0)
result.push_back("fizz");
else result.push_back(to_string(i));
}
return result;
}
};
13. 字符串查找
描述
对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1
。
您在真实的面试中是否遇到过这个题? 是
说明
在面试中我是否需要实现KMP算法?
- 不需要,当这种问题出现在面试中时,面试官很可能只是想要测试一下你的基础应用能力。当然你需要先跟面试官确认清楚要怎么实现这个题。
样例
如果 source = "source"
和 target = "target"
,返回 -1
。
如果 source = "abcdabcdefg"
和 target = "bcd"
,返回 1
。
挑战
O(n2)的算法是可以接受的。如果你能用O(n)的算法做出来那更加好。(提示:KMP)
class Solution {
public:
/**
* Returns a index to the first occurrence of target in source,
* or -1 if target is not part of source.
* @param source string to be scanned.
* @param target string containing the sequence of characters to match.
*/
int strStr(const char *source, const char *target) {
if(source == '\0') return -1;
if(target == '\0') return -1;
// write your code here
int m = strlen(source);
int n = strlen(target);
if(m == 0 && n == 0)
return 0;
int j;
int i;
for(i=0; i<m; i++){
for(j=0; j<n && i+j<m; j++){
if(source[i+j] != target[j])
break;
}
if(j == n)
return i;
}
return -1;
}
};
14. 二分查找
描述
给定一个排序的整数数组(升序)和一个要查找的整数target
,用O(logn)
的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1
。
您在真实的面试中是否遇到过这个题? 是
样例
在数组 [1, 2, 3, 3, 4, 5, 10]
中二分查找3
,返回2
。
class Solution {
public:
/**
* @param nums: The integer array.
* @param target: Target to find.
* @return: The first position of target. Position starts from 0.
*/
int binarySearch(vector<int> &nums, int target) {
// write your code here
if (nums.size() == 0) return -1;
int start = 0;
int end = nums.size() - 1;
// 要点1: 再找最后一个对象时,必须使用start + 1 < end,
// 当使用start < end时,在[1,1],1的场景下会出现死循环。
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
// 这里不能return,需要把end设置为mid,继续往前找。
end = mid;}
else if (nums[mid] > target)
end = mid;
else
start = mid;
}
// 要点2: 要把start先比较
if (nums[start] == target)
return start;
if (nums[end] == target)
return end;
return -1;
}
};
22. 平面列表
描述
给定一个列表,该列表中的每个要素要么是个列表,要么是整数。将其变成一个只包含整数的简单列表。
如果给定的列表中的要素本身也是一个列表,那么它也可以包含列表。
您在真实的面试中是否遇到过这个题? 是
样例
给定 [1,2,[1,2]]
,返回 [1,2,1,2]
。
给定 [4,[3,[2,[1]]]]
,返回 [4,3,2,1]
。
class Solution {
public:
// @param nestedList a list of NestedInteger
// @return a list of integer
vector<int> flatten(vector<NestedInteger> &nestedList) {
// Write your code here
vector<int> result;
addAll(result,nestedList);
return result;
}
void addAll(vector<int> &result,const vector<NestedInteger> &from){
for(int i=0;i<from.size();++i){
if(from[i].isInteger()){
result.push_back(from[i].getInteger());
}
else{
addAll(result,from[i].getList());
}
}
}
};
28. 搜索二维矩阵
描述
写出一个高效的算法来搜索 m × n矩阵中的值。
这个矩阵具有以下特性:
- 每行中的整数从左到右是排序的。
- 每行的第一个数大于上一行的最后一个整数。
您在真实的面试中是否遇到过这个题? 是
样例
考虑下列矩阵:
[
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
给出 target = 3
,返回 true
class Solution {
public:
/**
* @param matrix: matrix, a list of lists of integers
* @param target: An integer
* @return: a boolean, indicate whether matrix contains target
*/
bool searchMatrix(vector<vector<int>> &matrix, int target) {
// write your code here
int sizeRow=matrix.size();
if(sizeRow==0)
return false;
int sizeCol=matrix[0].size();
if(sizeCol==0)
return false;
int begin =0;
int end= sizeRow*sizeCol-1;
while(begin<=end)
{
int mid=(begin+end)/2;
int m=mid/sizeCol;
int n=mid%sizeCol;
if(matrix[m][n]==target)
return true;
else if(matrix[m][n]>target)
{
end=mid-1;
}
else
{
begin=mid+1;
}
}
return false;
}
};
30. 插入区间
描述
Given a non-overlapping interval list which is sorted by start point.
Insert a new interval into it, make sure the list is still in order and non-overlapping
(merge intervals if necessary).
您在真实的面试中是否遇到过这个题? 是
样例
Insert (2, 5)
into [(1,2), (5,9)]
, we get [(1,9)].
Insert (3, 4)
into [(1,2), (5,9)]
, we get [(1,2), (3,4), (5,9)]
.
/**
* Definition of Interval:
* classs Interval {
* int start, end;
* Interval(int start, int end) {
* this->start = start;
* this->end = end;
* }
*/
class Solution {
public:
/**
* Insert newInterval into intervals.
* @param intervals: Sorted interval list.
* @param newInterval: new interval.
* @return: A new interval list.
*/
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
vector<Interval> result;
size_t i = 0;
for (; i != intervals.size(); ++i) {
if (intervals[i].end < newInterval.start) result.push_back(intervals[i]);
else break;
}
for (; i != intervals.size(); ++i) {
if (newInterval.end < intervals[i].start) break;
else {
newInterval.start = min(newInterval.start, intervals[i].start);
newInterval.end = max(newInterval.end, intervals[i].end);
}
}
result.push_back(newInterval);
for (; i != intervals.size(); ++i) {
result.push_back(intervals[i]);
}
return result;
}
};
35. 翻转链表
描述
翻转一个链表
您在真实的面试中是否遇到过这个题? 是
样例
给出一个链表1->2->3->null,这个翻转后的链表为3->2->1->null
挑战
在原地一次翻转完成
/**
* Definition of singly-linked-list:
*
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: n
* @return: The new head of reversed linked list.
*/
ListNode * reverse(ListNode * head) {
// write your code here
if(!head || !head->next) return head;
ListNode* tmp = NULL;
while(head) {
ListNode * node = head->next;
head->next = tmp;
tmp = head;
head = node;
}
return tmp;
}
};
39. 恢复旋转排序数组
描述
给定一个旋转排序数组,在原地恢复其排序。
您在真实的面试中是否遇到过这个题? 是
说明
什么是旋转数组?
- 比如,原始数组为[1,2,3,4], 则其旋转数组可以是[1,2,3,4], [2,3,4,1], [3,4,1,2], [4,1,2,3]
样例
[4, 5, 1, 2, 3]
-> [1, 2, 3, 4, 5]
挑战
使用O(1)的额外空间和O(n)时间复杂度
class Solution {
public:
/**
* @param nums: An integer array
* @return: nothing
*/
void recoverRotatedSortedArray(vector<int> &nums) {
// write your code here
int p = 0;
int m = nums.size();
for(int i = 0; i < m-2; i++)
{
if(nums[i+1] < nums[i])
{
p = i;
break;
}
}
if(p!= 0)
{recover(nums, 0, p);
recover(nums, p+1, m-1);
recover(nums, 0, m-1);}
}
void recover(vector<int> &nums, int begin, int end)
{
int i = 0;int j = 0;
for(i = begin,j = end; i<begin+(end-begin+1)/2; i++, j--)
swap(nums[i], nums[j]);
}
};
41. 最大子数组
描述
给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
子数组最少包含一个数
您在真实的面试中是否遇到过这个题? 是
样例
给出数组[−2,2,−3,4,−1,2,1,−5,3]
,符合要求的子数组为[4,−1,2,1]
,其最大和为6
挑战
要求时间复杂度为O(n)
class Solution {
public:
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
int maxSubArray(vector<int> &nums) {
// write your code here
int size = nums.size();
if(size == 0) return 0;
if(size == 1) return nums[0];
int sum = 0; int maxsum = INT_MIN; int minsum = 0;
for(int i = 0; i<size; i++)
{
sum +=nums[i];
maxsum = max(sum - minsum, maxsum);
minsum = min(sum, minsum);
}
return maxsum;
}
};
44. 最小子数组
描述
给定一个整数数组,找到一个具有最小和的子数组。返回其最小和。
子数组最少包含一个数字
您在真实的面试中是否遇到过这个题? 是
样例
给出数组[1, -1, -2, 1],返回 -3
class Solution {
public:
/*
* @param nums: a list of integers
* @return: A integer indicate the sum of minimum subarray
*/
int minSubArray(vector<int> &nums) {
// write your code here
int size = nums.size();
if(size == 1) return nums[0];
int sum = 0; int minsum = INT_MAX;
for(int i = 0; i<size; i++)
{
sum = min(sum+nums[i], nums[i]);
minsum = min(sum,minsum);
}
return minsum;
}
};
46. Majority Element
描述
给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。
You may assume that the array is non-empty and the majority number always exist in the array.
您在真实的面试中是否遇到过这个题? 是
样例
给出数组[1,1,1,1,2,2,2],返回 1
挑战
要求时间复杂度为O(n),空间复杂度为O(1)
class Solution {
public:
/*
* @param nums: a list of integers
* @return: find a majority number
*/
int majorityNumber(vector<int> &nums) {
// write your code here
sort(nums.begin(), nums.end());
int size = nums.size();
int half = size/2;
int count = 1;
for(int i = 0; i<size-1; i++)
{
if(nums[i] == nums[i+1])
{
count++;
if(count > half)
return nums[i];
}
else count = 1;
}
}
};
53. 翻转字符串
描述
给定一个字符串,逐个翻转字符串中的每个单词。
您在真实的面试中是否遇到过这个题? 是
说明
- 单词的构成:无空格字母构成一个单词
- 输入字符串是否包括前导或者尾随空格?可以包括,但是反转后的字符不能包括
- 如何处理两个单词间的多个空格?在反转字符串中间空格减少到只含一个
样例
给出s = "the sky is blue",返回"blue is sky the"
class Solution {
public:
/*
* @param s: A string
* @return: A string
*/
string reverseWords(string s) {
int size=s.size(), len=0, start=0, end=0;
reverse(s.begin(), s.end());
for(;start<size; ++start) {
if(s[start]!=' ') {
if(len!=0) {
s[len++]=' ';
}
int end=start;
while(end<size&&s[end]!=' ') s[len++]=s[end++];
reverse(s.begin()+len-(end-start), s.begin()+len);
start=end;
}
}
return s.substr(0, len);
}
};
55. 比较字符串
描述
比较两个字符串A和B,确定A中是否包含B中所有的字符。字符串A和B中的字符都是 大写字母
在 A 中出现的 B 字符串里的字符不需要连续或者有序。
您在真实的面试中是否遇到过这个题? 是
样例
给出 A = "ABCD"
B = "ACD"
,返回 true
给出 A = "ABCD"
B = "AABC"
, 返回 false
class Solution {
public:
/**
* @param A: A string
* @param B: A string
* @return: if string A contains all of the characters in B return true else return false
*/
bool compareStrings(string A, string B) {
// write your code here
if(B.size() == 0) return true;
int count = 0;
for(int i =0;i<B.size();i++)
{
for(int j = 0; j<A.size(); j++)
{
if(A[j] == B[i])
{
A[j] = 0;
count ++;
break;
}
}
}
if(count == B.size()) return true;
else return false;
}
};
56. 两数之和
描述
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。
你需要实现的函数twoSum
需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。
你可以假设只有一组答案。
您在真实的面试中是否遇到过这个题? 是
样例
给出 numbers = [2, 7, 11, 15]
, target = 9
, 返回 [0, 1]
.
挑战
Either of the following solutions are acceptable:
- O(n) Space, O(nlogn) Time
- O(n) Space, O(n) Time
class Solution {
public:
/**
* @param numbers: An array of Integer
* @param target: target = numbers[index1] + numbers[index2]
* @return: [index1, index2] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target) {
unordered_map<int,int>mapping;
vector<int> a;
for(int i=0;i<nums.size();i++)
mapping[nums[i]]=i;
for(int i=0;i<nums.size();i++)
{
unsigned int result=target-nums[i];
if(mapping.find(result)!=mapping.end()&&mapping[result]>i)
{ a.push_back(i);
a.push_back(mapping[result]);
}
}
return a;
}
};
60. 搜索插入位置
描述
给定一个排序数组和一个目标值,如果在数组中找到目标值则返回索引。如果没有,返回到它将会被按顺序插入的位置。
你可以假设在数组中无重复元素。
您在真实的面试中是否遇到过这个题? 是
样例
[1,3,5,6],5 → 2
[1,3,5,6],2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6],0 → 0
挑战
O(log(n)) time
class Solution {
public:
/**
* @param A: an integer sorted array
* @param target: an integer to be inserted
* @return: An integer
*/
int searchInsert(vector<int> &A, int target) {
// write your code here
int size = A.size();
if(A.size() == 0) return 0;
for(int i = 0; i<A.size(); i++)
{
if(A[i] == target) return i;
if(A[i] > target) return i;
}
if(A[-1] < target) return size;
}
};
64. 合并排序数组
描述
合并两个排序的整数数组A和B变成一个新的数组。
你可以假设A具有足够的空间(A数组的大小大于或等于m+n)去添加B中的元素。
您在真实的面试中是否遇到过这个题? 是
样例
给出 A = [1, 2, 3, empty, empty]
, B = [4, 5]
合并之后 A 将变成 [1,2,3,4,5]
class Solution {
public:
/*
* @param A: sorted integer array A which has m elements, but size of A is m+n
* @param m: An integer
* @param B: sorted integer array B which has n elements
* @param n: An integer
* @return: nothing
*/
void mergeSortedArray(int A[], int m, int B[], int n) {
// write your code here
int all = m + n;
while(m >= 0 && n >= 0)
{
if(A[m - 1] > B[n - 1]) A[--all] = A[--m];
else A[--all] = B[--n];
}
while(n >= 0) A[--all] = B[--n];
}
};
66. 二叉树的前序遍历
给出一棵二叉树,返回其节点值的前序遍历。
样例
给出一棵二叉树 {1,#,2,3}
,
1
\
2
/
3
返回 [1,2,3]
.
挑战
你能使用非递归实现么?
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
vector<int> preorderTraversal(TreeNode * root) {
// write your code here
vector<int> nums;
preorder(root, nums);
return nums;
}
void preorder(TreeNode * root, vector<int> &nums)
{
if(root != NULL)
{
nums.push_back(root -> val);
preorder(root -> left, nums);
preorder(root -> right, nums);
}
}
};
67. 二叉树的中序遍历
给出一棵二叉树,返回其中序遍历
样例
给出二叉树 {1,#,2,3}
,
1
\
2
/
3
返回 [1,3,2]
.
挑战
你能使用非递归算法来实现么?
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Inorder in ArrayList which contains node values.
*/
vector<int> inorderTraversal(TreeNode * root) {
// write your code here
vector<int> nums;
inorder(root, nums);
return nums;
}
void inorder(TreeNode * root, vector<int> &nums)
{
if(root != NULL)
{
inorder(root -> left, nums);
nums.push_back(root -> val);
inorder(root -> right, nums);
}
}
};
68. 二叉树的后序遍历
给出一棵二叉树,返回其节点值的后序遍历。
样例
给出一棵二叉树 {1,#,2,3}
,
1
\
2
/
3
返回 [3,2,1]
挑战
你能使用非递归实现么?
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
// write your code here
vector<int> nums;
postorder(root, nums);
return nums;
}
void postorder(TreeNode * root, vector<int> &nums)
{
if(root != NULL)
{
postorder(root -> left, nums);
postorder(root -> right, nums);
nums.push_back(root -> val);
}
}
};
69. 二叉树的层次遍历
给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问)
样例
给一棵二叉树 {3,9,20,#,#,15,7}
:
3
/ \
9 20
/ \
15 7
返回他的分层遍历结果:
[
[3],
[9,20],
[15,7]
]
挑战
挑战1:只使用一个队列去实现它
挑战2:用DFS算法来做
class Solution {
vector<vector<int>> ans;
void dfs(TreeNode * node,int level)
{
if (!node) return;
if (ans.size()<level+1)
ans.resize(level+1);
dfs(node->left,level+1);
vector<int>& v = ans[level];
v.push_back(node->val);
dfs(node->right,level+1);
}
public:
vector<vector<int>> levelOrder(TreeNode * root) {
dfs(root,0);
return ans;
}
};
80. 中位数
给定一个未排序的整数数组,找到其中位数。
中位数是排序后数组的中间值,如果数组的个数是偶数个,则返回排序后数组的第N/2个数。
样例
给出数组[4, 5, 1, 2, 3], 返回 3
给出数组[7, 9, 4, 5],返回 5
挑战
时间复杂度为O(n)
class Solution {
public:
/**
* @param nums: A list of integers
* @return: An integer denotes the middle number of the array
*/
int median(vector<int> &nums) {
// write your code here
sort(nums.begin(), nums.end());
int size = nums.size();
if(size%2 == 0) return nums[size/2 -1];
else return nums[size/2 ];
}
};
82. 落单的数
给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字。
样例
给出 [1,2,2,1,3,4,3],返回 4
挑战
一次遍历,常数级的额外空间复杂度
class Solution {
public:
/**
* @param A: An integer array
* @return: An integer
*/
int singleNumber(vector<int> &A) {
map<int,int> m;
for(int i=0;i<A.size();i++){
m[A[i]]++;
}
for(int i=0;i<A.size();i++){
if(m[A[i]]==1){
return A[i];
}
}
return -1;
}
};
85. 在二叉查找树中插入节点
给定一棵二叉查找树和一个新的树节点,将节点插入到树中。
你需要保证该树仍然是一棵二叉查找树。
样例
给出如下一棵二叉查找树,在插入节点6之后这棵二叉查找树可以是这样的:
2 2
/ \ / \
1 4 --> 1 4
/ / \
3 3 6
挑战
能否不使用递归?
注意事项
You can assume there is no duplicate values in this tree + node.
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: The root of the binary search tree.
* @param node: insert this node into the binary search tree
* @return: The root of the new binary search tree.
*/
TreeNode* insertNode(TreeNode* root, TreeNode* node) {
if(root == NULL) return node;
if(root -> val > node -> val)
root -> left = insertNode(root -> left, node);
else if(root -> val < node -> val)
root -> right = insertNode(root -> right, node);
return root;
}
};
93. 平衡二叉树
给定一个二叉树,确定它是高度平衡的。对于这个问题,一棵高度平衡的二叉树的定义是:一棵二叉树中每个节点的两个子树的深度相差不会超过1。
样例
给出二叉树 A={3,9,20,#,#,15,7}
, B={3,#,20,15,7}
A) 3 B) 3
/ \ \
9 20 20
/ \ / \
15 7 15 7
二叉树A是高度平衡的二叉树,但是B不是
输入测试数据 (每行一个参数)
class Solution { // return the height of current root, -1 means not balanced
int helper(TreeNode* node) {
if (!node) return 0;
int l = helper(node->left);
if (l == -1) return -1; // early stop
int r = helper(node->right);
if (r == -1 or abs(l - r) > 1)
return -1;
return 1 + max(l, r);
}
public:
bool isBalanced(TreeNode* root) {
return helper(root) != -1;
}
};
96. 链表划分
给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。
你应该保留两部分内链表节点原有的相对顺序。
样例
给定链表 1->4->3->2->5->2->null,并且 x=3
返回 1->2->2->4->3->5->null
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list
* @param x: An integer
* @return: A ListNode
*/
ListNode * partition(ListNode * head, int x) {
ListNode * d1 = new ListNode(0);
ListNode * d2 = new ListNode(0);
ListNode * p = d1;
ListNode * q = d2;
ListNode *cur = head;
while(cur != NULL)
{
if(cur -> val < x)
{
p ->next = cur;
p = p->next;
}
if(cur -> val >= x)
{
q ->next = cur;
q = q -> next;
}
cur = cur ->next;
}
q -> next =NULL;
p ->next = d2->next;
return d1->next;
}
};
97. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的距离。
样例
给出一棵如下的二叉树:
1
/ \
2 3
/ \
4 5
这个二叉树的最大深度为3
.
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param root: The root of binary tree.
* @return: An integer
*/
int maxDepth(TreeNode *root) {
if (root == NULL) {
return 0;
}
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return left > right ? left + 1 : right + 1;
}
};
100. 删除排序数组中的重复数字
给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度。
不要使用额外的数组空间,必须在原地没有额外空间的条件下完成。
样例
给出数组A =[1,1,2],你的函数应该返回长度2,此时A=[1,2]。
class Solution {
public:
/*
* @param nums: An ineger array
* @return: An integer
*/
int removeDuplicates(vector<int> &nums) {
// write your code here
if(nums.size() == 0) return NULL;
int len = 0;
for(int i = 1; i<nums.size(); i++)
if(nums[len] != nums[i])
nums[++len] = nums[i];
return len+1;
}
};
101. 删除排序数组中的重复数字 II
跟进“删除重复数字”:
如果可以允许出现两次重复将如何处理?
class Solution {
public:
/**
* @param A: a list of integers
* @return : return an integer
*/
int removeDuplicates(vector<int> &nums) {
// write your code here
if(nums.size() == 0) return NULL;
int len = 2;
for(int i =2; i<nums.size(); i++)
{
if(nums[len-2] != nums[i])
nums[len++] = nums[i];
}
return len;
}
};
109. 数字三角形
给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。
样例
比如,给出下列数字三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
从顶到底部的最小路径和为11 ( 2 + 3 + 5 + 1 = 11)。
注意事项
如果你只用额外空间复杂度O(n)的条件下完成可以获得加分,其中n是数字三角形的总行数。
class Solution {
public:
/**
* @param triangle: a list of lists of integers
* @return: An integer, minimum path sum
*/
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> dp(triangle.back());
for (int i = triangle.size() - 2; i >= 0; --i) {
for (int j = 0; j <= i; ++j) {
dp[j] = min(dp[j], dp[j + 1]) + triangle[i][j];
}
}
return dp[0];
}
};
110. 最小路径和
给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。
注意事项
你在同一时间只能向下或者向右移动一步
class Solution {
public:
/**
* @param grid: a list of lists of integers.
* @return: An integer, minimizes the sum of all numbers along its path
*/
int minPathSum(vector<vector<int> > &grid) {
// write your code here
int m=grid.size(), n=grid[0].size();
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
if(i||j)
if(i==0)
grid[i][j]=grid[i][j-1]+grid[i][j];
else if(j==0)
grid[i][j]=grid[i-1][j]+grid[i][j];
else
grid[i][j]=min(grid[i-1][j],grid[i][j-1])+grid[i][j];
}
return grid[m-1][n-1];
}
};
111. 爬楼梯
假设你正在爬楼梯,需要n步你才能到达顶部。但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?
样例
比如n=3,1+1+1=1+2=2+1=3,共有3种不同的方法
返回 3
class Solution {
public:
/**
* @param n: An integer
* @return: An integer
*/
int climbStairs(int n) {
// write your code here
if(n == 0) return 0;
if(n == 1) return 1;
if(n == 2) return 2;
vector<int> nums(n);
nums[0] = 1;
nums[1] = 2;
for(int i = 2;i<n;i++){
nums[i] = nums[i-1] + nums[i-2];
}
return nums[n-1];
}
};
112. 删除排序链表中的重复元素
给定一个排序链表,删除所有重复的元素每个元素只留下一个。
样例
给出 1->1->2->null
,返回 1->2->null
给出 1->1->2->3->3->null
,返回 1->2->3->null
class Solution {
public:
ListNode * deleteDuplicates(ListNode * head) {
if(!head) return head;
ListNode *p = head;
while (p) {
while(p->next && p->val == p->next->val)
p->next = p->next->next;
p = p->next;
}
return head;
}
};
114. 不同的路径
有一个机器人的位于一个 m × n 个网格左上角。
机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角。
问有多少条不同的路径?
样例
给出 m = 3
和 n = 3
, 返回 6
.
给出 m = 4
和 n = 5
, 返回 35
.
注意事项
n和m均不超过100
class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> path(n, 1);
for (int i = 1; i < m; ++i){
for (int j = 1; j < n; ++j){
path[j] += path[j - 1];
}
}
return path[n-1];
}
};
141. x的平方根
实现 int sqrt(int x)
函数,计算并返回 x 的平方根。
样例
sqrt(3) = 1
sqrt(4) = 2
sqrt(5) = 2
sqrt(10) = 3
挑战
O(log(x))
class Solution {
public:
/**
* @param x: An integer
* @return: The sqrt of x
*/
int sqrt(int x) {
// write your code here
if (x == 0)
{
return 0;
}
int left = 1, right = 46341;
int mid = 0;
while (left < right)
{
//cout << mid << endl;
if (mid == (left + right) / 2)
{
break;
}
mid = (left + right) / 2;
if (mid*mid == x)
{
return mid;
} else if (mid*mid < x)
{
left = mid;
} else
{
right = mid;
}
}
return mid;
}
};
155. 二叉树的最小深度
给定一个二叉树,找出其最小深度。
二叉树的最小深度为根节点到最近叶子节点的距离。
样例
给出一棵如下的二叉树:
1
/ \
2 3
/ \
4 5
这个二叉树的最小深度为 2
class Solution {
public:
/**
* @param root: The root of binary tree
* @return: An integer
*/
int minDepth(TreeNode * root) {
// write your code here
if (root == NULL) {
return 0;
}
int left = minDepth(root -> left);
int right = minDepth(root -> right);
if (left == 0) {
return right + 1;
} else if (right == 0) {
return left + 1;
}
return min(left, right) + 1;
}
};
156. 合并区间
给出若干闭合区间,合并所有重叠的部分。
样例
Given intervals => merged intervals:
[ [
(1, 3), (1, 6),
(2, 6), => (8, 10),
(8, 10), (15, 18)
(15, 18) ]
]
挑战
O(n log n) 的时间和 O(1) 的额外空间。
输入测试数据 (每行一个参数)
class Solution {
public:
vector<Interval> merge(vector<Interval>& intervals) {
vector<Interval> res;
if (intervals.empty()) return res;
sort(intervals.begin(), intervals.end(), [](Interval& a, Interval& b){return a.start < b.start;});
int s = intervals[0].start, e = intervals[0].end;
for (int i = 1; i < intervals.size(); ++i) {
if (intervals[i].start > e) {
res.emplace_back(s, e);
s = intervals[i].start;
}
e = max(e, intervals[i].end);
}
res.emplace_back(s, e);
return res;
}
};
165. 合并两个排序链表
将两个排序链表合并为一个新的排序链表
样例
给出 1->3->8->11->15->null
,2->null
, 返回 1->2->3->8->11->15->null
。
class Solution {
public:
ListNode * mergeTwoLists(ListNode * l1, ListNode * l2) {
if(!l1) return l2;if(!l2) return l1;
if(l1->val < l2->val) {
l1->next = mergeTwoLists(l1->next, l2);return l1;
} else {
l2->next = mergeTwoLists(l2->next, l1);return l2;
}
}
};
class Solution {
public:
/**
* @param l1: ListNode l1 is the head of the linked list
* @param l2: ListNode l2 is the head of the linked list
* @return: ListNode head of linked list
*/
ListNode * mergeTwoLists(ListNode * l1, ListNode * l2) {
// write your code here
if(l1 == NULL && l2 == NULL) return NULL;
if(l1 == NULL) return l2;
if(l2 == NULL) return l1;
int val = 0;
if(l1 -> val > l2 -> val)
{
val = l2 -> val;
l2 = l2 -> next;
}
else
{
val = l1 -> val;
l1 = l1 -> next;
}
ListNode *head = new ListNode(val);
ListNode *n = head;
while(l1 != NULL && l2 != NULL)
{
int val = 0;
if(l1 -> val > l2 -> val)
{
val = l2 -> val;
l2 = l2 -> next;
}
else
{
val = l1 -> val;
l1 = l1 -> next;
}
ListNode *n2 = new ListNode(val);
n -> next = n2;
n = n -> next;
n = n2;
}
while(l1 != NULL)
{
ListNode *n2 = new ListNode(l1 -> val);
l1 = l1 -> next;
n -> next = n2;
n = n2;
}
while(l2 != NULL)
{
ListNode *n2 = new ListNode(l2 -> val);
l2 = l2 -> next;
n -> next = n2;
n = n2;
}
n -> next = NULL;
return head;
}
};
167. 链表求和
你有两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反
的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。
样例
给出两个链表 3->1->5->null
和 5->9->2->null
,返回 8->0->8->null
class Solution {
public:
/**
* @param l1: the first list
* @param l2: the second list
* @return: the sum list of l1 and l2
*/
ListNode * addLists(ListNode * l1, ListNode * l2) {
// write your code here
if(l2==NULL) return l1;
ListNode *p=new ListNode(0);
p->next=l1;
int flag=0;
while(p->next!=NULL){
p->next->val+=l2->val+flag;
if(p->next->val>=10){
p->next->val-=10;
flag=1;
}
else flag=0;
p=p->next;
l2=l2->next==NULL&&p->next!=NULL?new ListNode(0):l2->next;
}
while(l2!=NULL){
p->next=new ListNode(l2->val+flag);
if(p->next->val >= 10){
p->next->val-=10;
flag=1;
}
else flag=0;
l2=l2->next;
p=p->next;
}
if(flag==1) p->next=new ListNode(1);
return l1;
}
};
172. 删除元素
给定一个数组和一个值,在原地删除与值相同的数字,返回新数组的长度。
元素的顺序可以改变,并且对新的数组不会有影响。
样例
给出一个数组 [0,4,4,0,0,2,4,4],和值 4
返回 4 并且4个元素的新数组为[0,0,0,2]
class Solution {
public:
/*
* @param A: A list of integers
* @param elem: An integer
* @return: The new length after remove
*/
int removeElement(vector<int> &A, int elem) {
// write your code here
if(A.size() == 0) return 0;
for(int i = A.size()-1; i>=0; i--)
if(A[i] == elem)
A.erase(A.begin()+i);
return A.size();
}
};
173. 链表插入排序
用插入排序对链表排序
样例
Given 1->3->2->0->null
, return 0->1->2->3->null
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
ListNode dummy(0), *st = head; // st: st and nodes before st are sorted
dummy.next = head;
while (st) {
if (st->next and st->next->val < st->val) {
auto p = &dummy, q = st->next;
while (p->next->val < st->next->val) // find insertion point
p = p->next;
st->next = q->next;
q->next = p->next;
p->next = q;
}
else st = st->next;
}
return dummy.next;
}
};
174. 删除链表中倒数第n个节点
给定一个链表,删除链表中倒数第n个节点,返回链表的头节点。
样例
给出链表1->2->3->4->5->null和 n = 2.
删除倒数第二个节点之后,这个链表将变成1->2->3->5->null.
挑战
O(n)时间复杂度
注意事项
链表中的节点个数大于等于n
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param head: The first node of linked list.
* @param n: An integer
* @return: The head of linked list.
*/
ListNode * removeNthFromEnd(ListNode * head, int n) {
// write your code here
ListNode *del=new ListNode(0);
del->next=head;
ListNode *temp=del;
for(int i=0;i<n;i++){head=head->next;}
while(head!=NULL){head=head->next;temp=temp->next;}
temp->next=temp->next->next;
return del->next;
}
};
175. 翻转二叉树
翻转一棵二叉树
样例
1 1
/ \ / \
2 3 => 3 2
/ \
4 4
挑战
递归固然可行,能否写个非递归的?
class Solution {
public:
/**
* @param root: a TreeNode, the root of the binary tree
* @return: nothing
*/
void invertBinaryTree(TreeNode * root) {
// write your code here
if(root)
{
swap(root -> left, root -> right);
invertBinaryTree(root -> left);
invertBinaryTree(root -> right);
}
}
};
372. Delete Node in a Linked List
给定一个单链表中的一个等待被删除的节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。
样例
Linked list is 1->2->3->4
, and given node 3
, delete the node in place 1->2->4
class Solution {
public:
/*
* @param node: the node in the list should be deletedt
* @return: nothing
*/
void deleteNode(ListNode * node) {
// write your code here
node -> val = node -> next -> val;
node -> next = node -> next -> next;
}
};
389. 判断数独是否合法
请判定一个数独是否有效。
该数独可能只填充了部分数字,其中缺少的数字用 .
表示。
样例
The following partially filed sudoku is valid.
说明
什么是 数独
?
注意事项
一个合法的数独(仅部分填充)并不一定是可解的。我们仅需使填充的空格有效即可。
class Solution {
public:
/*
* @param board: the board
* @return: whether the Sudoku is valid
*/
bool isValidSudoku(vector<vector<char>> &board) {
vector<vector<bool> > rows(9, vector<bool>(9, false));
vector<vector<bool> > cols(9, vector<bool>(9, false));
vector<vector<bool> > blocks(9, vector<bool>(9, false));
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
if (board[i][j] == '.') continue;
int c = board[i][j] - '1';
if (rows[i][c] || cols[j][c] || blocks[i - i % 3 + j / 3][c])
return false;
rows[i][c] = cols[j][c] = blocks[i - i % 3 + j / 3][c] = true;
}
}
return true; // write your code here
}
};
407. 加一
给定一个非负数,表示一个数字数组,在该数的基础上+1,返回一个新的数组。
该数字按照数位高低进行排列,最高位的数在列表的最前面。
样例
给定 [1,2,3]
表示 123, 返回 [1,2,4]
.
给定 [9,9,9]
表示 999, 返回 [1,0,0,0]
.
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param digits: a number represented as an array of digits
* @return: the result
*/
vector<int> plusOne(vector<int> &digits) {
// write your code here
digits.back() +=1;
for(int i = digits.size()-1; i > 0; i--)
if(digits[i] > 9)
{
digits[i] = digits[i] % 10;
digits[i-1]++;
}
if(digits[0] > 9)
{
digits[0] = digits[0] % 10;
digits.insert(digits.begin(),1);
}
return digits;
}
};
408. 二进制求和
给定两个二进制字符串,返回他们的和(用二进制表示)。
样例
a = 11
b = 1
返回 100
class Solution {
public:
/*
* @param a: a number
* @param b: a number
* @return: the result
*/
string addBinary(string &a, string &b) {
string ret;
int m = a.size(), n = b.size();
int i = m - 1, j = n - 1, val = 0;
while (i > -1 || j > -1 || val)
{
if (i > -1)
val += a[i--] - 48;
if (j > -1)
val += b[j--] - 48;
ret = to_string(val % 2) + ret;
val /= 2;
}
return ret;
}
};
413. 反转整数
将一个整数中的数字进行颠倒,当颠倒后的整数溢出时,返回 0 (标记为 32 位整数)。
样例
给定 x = 123
,返回 321
给定 x = -123
,返回 -321
class Solution {
public:
/**
* @param n: the integer to be reversed
* @return: the reversed integer
*/
int reverseInteger(int x) {
// write your code here
long res = 0;
while (x != 0) {
res = res * 10 + x % 10;
x /= 10;
}
return res > INT_MAX or res < INT_MIN ? 0 : res;
}
};
415. 有效回文串
给定一个字符串,判断其是否为一个回文串。只考虑字母和数字,忽略大小写。
样例
"A man, a plan, a canal: Panama"
是一个回文。
"race a car"
不是一个回文。
挑战
O(n) 时间复杂度,且不占用额外空间。
注意事项
你是否考虑过,字符串有可能是空字符串?这是面试过程中,面试官常常会问的问题。
在这个题目中,我们将空字符串判定为有效回文。
class Solution {
public:
/**
* @param s: A string
* @return: Whether the string is a valid palindrome
*/
bool isPalindrome(string &s) {
if(s.size() == 0) return 1;
for(int i = s.size()-1; i>=0; i--)
{
if((s[i] >= 65 && s[i] <=90)||(s[i] >= 97 && s[i] <= 122)|| (s[i] >= 48 && s[i] <= 57))
{
if(s[i] >= 65 && s[i] <=90)
{
s[i] = 32 + s[i];
}
}
else s.erase(s.begin()+i);
}
int i = 0; int j = 0;
for(i = 0, j = s.size()-1; i<s.size()/2; i++, j--)
{
if(s[i] != s[j]) return false;
}
return true;
}
};
420. 报数
报数指的是,按照其中的整数的顺序进行报数,然后得到下一个数。如下所示:
1, 11, 21, 1211, 111221, ...
1
读作 "one 1"
-> 11
.
11
读作 "two 1s"
-> 21
.
21
读作 "one 2, then one 1"
-> 1211
.
给定一个整数 n
, 返回 第 n
个顺序。
样例
给定 n = 5
, 返回 "111221"
.
注意事项
整数的顺序将表示为一个字符串。
class Solution {
public:
/*
* @param n: the nth
* @return: the nth sequence
*/
string countAndSay(int n) {
if (n <= 0) return "";
string res = "1";
while (--n) {
string cur = "";
for (int i = 0; i < res.size(); ++i) {
int cnt = 1;
while (i + 1 < res.size() && res[i] == res[i + 1]) {
++cnt;
++i;
}
cur += to_string(cnt) + res[i];
}
res = cur;
}
return res;
}
};
422. 最后一个单词的长度
给定一个字符串, 包含大小写字母、空格' '
,请返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0
。
样例
给定 s = "Hello World"
,返回 5
。
注意事项
一个单词的界定是,由字母组成,但不包含任何的空格。
class Solution {
public:
/**
* @param s: A string
* @return: the length of last word
*/
int lengthOfLastWord(string &s) {
int result = 0;
for(int i = s.length()-1;i>=0;i--){
if(s[i]!=' '){
result++;
}else{
if(result)
return result;
}
}
return result;
}
};
423. 有效的括号序列
给定一个字符串所表示的括号序列,包含以下字符: '(', ')'
, '{'
, '}'
, '['
and ']'
, 判定是否是有效的括号序列。
样例
括号必须依照 "()"
顺序表示, "()[]{}"
是有效的括号,但 "([)]"
则是无效的括号。
class Solution {
public:
/**
* @param s: A string
* @return: whether the string is a valid parentheses
*/
bool isValidParentheses(string &s) {
// write your code here
std::stack<int> stack1;
unordered_map<int, int> mapping = {{'(',')'},{'{', '}'}, {'[',']'}};
for(int i = 0; s[i] != '\0'; i++)
{
if(s[i] == '('||s[i] == '{'||s[i] == '[')
stack1.push(s[i]);
else {
if (stack1.empty() || mapping.find(stack1.top()) == mapping.end() || mapping[stack1.top()] != s[i]) {
return false;
}
stack1.pop();
}
}
return stack1.size() == 0;
}
};
433. 岛屿的个数
给一个01矩阵,求不同的岛屿的个数。
0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
样例
在矩阵:
[
[1, 1, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 0, 0, 1, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 1]
]
中有 3
个岛.
输入测试数据 (每行一个参数)
class Solution{
bool dfs(int i,int j,vector<vector<bool>> &grid)
{
if(i>=0&&i<grid.size()&&j>=0&&j<grid[i].size()&&grid[i][j]==true)
{
grid[i][j] = false;
dfs(i-1,j,grid);
dfs(i+1,j,grid);
dfs(i,j-1,grid);
dfs(i,j+1,grid);
return true;
}
return false;
}
public:
int numIslands(vector<vector<bool>> &grid) {
int num = 0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[i].size();j++)
{
if(dfs(i,j,grid))
num++;
}
}
return num;
}
};
451. 两两交换链表中的节点
给一个链表,两两交换其中的节点,然后返回交换后的链表。
样例
给出 1->2->3->4
, 你应该返回的链表是 2->1->4->3
。
挑战
你的算法只能使用常数的额外空间,并且不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param head: a ListNode
* @return: a ListNode
*/
ListNode * swapPairs(ListNode * head) {
ListNode* dummy = new ListNode(-1);
ListNode* prev = dummy;
dummy->next = head;
while (prev->next && prev->next->next) {
ListNode* next = prev->next->next;
prev->next->next = next->next;
next->next = prev->next;
prev->next = next;
prev = next->next;
}
return dummy->next;
}
};
453. 将二叉树拆成链表
将一棵二叉树按照前序遍历拆解成为一个假链表
。所谓的假链表是说,用二叉树的 right 指针,来表示链表中的 next 指针。
样例
1
\
1 2
/ \ \
2 5 => 3
/ \ \ \
3 4 6 4
\
5
\
6
挑战
不使用额外的空间耗费。
注意事项
不要忘记将左儿子标记为 null,否则你可能会得到空间溢出或是时间溢出。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param root: a TreeNode, the root of the binary tree
* @return: nothing
*/
void flatten(TreeNode * root) {
if (!root) return;
auto rnode = root->right;
flatten(root->left);
root->right = root->left;
root->left = NULL;
while(root->right) root = root->right;
root->right = rnode;
flatten(rnode);
}
};
469. Same Tree
检查两棵二叉树是否等价。等价的意思是说,首先两棵二叉树必须拥有相同的结构,并且每个对应位置上的节点上的数都相等。
样例
1 1
/ \ / \
2 2 and 2 2
/ /
4 4
就是两棵等价的二叉树。
1 1
/ \ / \
2 3 and 2 3
/ \
4 4
就不是等价的。
class Solution {
public:
/**
* @param a: the root of binary tree a.
* @param b: the root of binary tree b.
* @return: true if they are identical, or false.
*/
bool isIdentical(TreeNode * a, TreeNode * b) {
// write your code here
if(a== NULL && b == NULL)
return true;
if(a == NULL || b == NULL)
return false;
if(a->val != b->val)
return false;
return isIdentical(a->left, b->left) && isIdentical(a->right, b->right);
}
};
480. 二叉树的所有路径
给一棵二叉树,找出从根节点到叶子节点的所有路径。
样例
给出下面这棵二叉树:
1
/ \
2 3
\
5
所有根到叶子的路径为:
[
"1->2->5",
"1->3"
]
输入测试数据 (每行一个参数)
vector<string> result;
class Solution {
public:
string to_str(int x){stringstream os;os << x;return os.str();}
vector<string> binaryTreePaths(TreeNode* root) {
dfs(root,(string)"");
return result;
}
private:
void dfs(TreeNode *root,string s){
if(!root) return;
s+=to_str(root->val)+"->";
if(!root->left && !root->right){
result.push_back(s.substr(0,s.size()-2));
}
dfs(root->left,s);
dfs(root->right,s);
}
};
488. 快乐数
写一个算法来判断一个数是不是"快乐数"。
一个数是不是快乐是这么定义的:对于一个正整数,每一次将该数替换为他每个位置上的数字的平方和,然后重复这个过程直到这个数变为1,或是无限循环但始终变不到1。如果可以变为1,那么这个数就是快乐数。
样例
19 就是一个快乐数。
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
输入测试数据 (每行一个参数)
class Solution {
public:
bool isHappy(int n) {
while (n != 1 && n != 4) {
int t = 0;
while (n) {
t += (n % 10) * (n % 10);
n /= 10;
}
n = t;
}
return n == 1;
}
};
491. 回文数
判断一个正整数是不是回文数。
回文数的定义是,将这个数反转之后,得到的数仍然是同一个数。
样例
11
, 121
, 1
, 12321
这些是回文数。
23
, 32
, 1232
这些不是回文数。
注意事项
给的数一定保证是32位正整数,但是反转之后的数就未必了。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param num: a positive number
* @return: true if it's a palindrome or false
*/
bool isPalindrome(int num) {
string s = to_string(num);
string t = s;
reverse(s.begin(), s.end());
return s == t;
}
};
514. 栅栏染色
我们有一个栅栏,它有n
个柱子,现在要给柱子染色,有k
种颜色可以染。
必须保证不存在超过2个相邻的柱子颜色相同,求有多少种染色方案。
样例
n
= 3, k
= 2, return 6
post 1, post 2, post 3
way1 0 0 1
way2 0 1 0
way3 0 1 1
way4 1 0 0
way5 1 0 1
way6 1 1 0
注意事项
n
和k
都是非负整数
输入测试数据 (每行一个参数)
class Solution {
public:
int numWays(int n, int k) {
int * store = new int[n];
if (n == 1)
return k;
if (n == 2)
return k * k;
store[0] = k;
store[1] = k * k;
for (int i = 2; i < n; i++)
{
store[i] = (store[i - 1] + store[i - 2])*(k - 1);
}
return store[n - 1];
}
};
517. 丑数
写一个程序来检测一个整数是不是丑数
。
丑数的定义是,只包含质因子 2, 3, 5
的正整数。比如 6, 8 就是丑数,但是 14 不是丑数以为他包含了质因子 7。
样例
给出 num = 8
,返回 true
。
给出 num = 14
,返回 false
。
注意事项
可以认为 1
是一个特殊的丑数。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param num: An integer
* @return: true if num is an ugly number or false
*/
bool isUgly(int num) {
if(num == 0) return false;
// write your code here
while(num % 2 == 0)
num = num / 2;
while(num % 3 == 0)
num = num / 3;
while(num % 5 == 0)
num = num / 5;
if(num == 1) return true;
else return false;
}
};
551. 嵌套列表的加权和
给一个嵌套的整数列表, 返回列表中所有整数由它们的深度加权后的总和. 每一个元素可能是一个整数或一个列表(其元素也可能是整数或列表)
样例
给出列表 [[1,1],2,[1,1]]
, 返回 10
. (4个'1'的深度是 2, 1个'2'的深度是1, 4 * 1 * 2 + 1 * 2 * 1 = 10)
给出列表 [1,[4,[6]]]
, 返回 27
. (1个 '1' 的深度是1, 1个 '4' 的深度是2, 以及1个 '6'的深度是3, 1 + 4 * 2 + 6 * 3 = 27)
class Solution {
public:
int depthSum(const vector<NestedInteger>& nestedList) {
// Write your code here
return calculate(nestedList,1);
}
int calculate(const vector<NestedInteger>& nestedList,int count){
int sum=0;
for(int i=0;i<nestedList.size();i++){
if(nestedList[i].isInteger()) sum+=nestedList[i].getInteger()*count;
else sum+=calculate(nestedList[i].getList(),count+1);
}
return sum;
}
};
655. Add Strings
以字符串的形式给出两个非负整数 num1
和 num2
,返回 num1
和 num2
的和。
样例
给定 num1 = "123"
,num2 = "45"
返回 "168"
注意事项
- num1 和 num2 的长度都小于5100。
- num1 和 num2 都只包含数字 0-9。
- num1 和 num2 都不包含任何前导零。
- 您不能使用任何内置的BigInteger库内的方法或直接将输入转换为整数。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param num1: a non-negative integers
* @param num2: a non-negative integers
* @return: return sum of num1 and num2
*/
string addStrings(string &num1, string &num2) {
// write your code here
string num;
int m = num1.size()-1; int n = num2.size()-1;
int temp = 0;
while(m>=0 || n >=0 || temp)
{
if(m>=0) temp = temp + num1[m--] - 48;
if(n>=0) temp = temp + num2[n--] - 48;
num = to_string(temp % 10) + num;
temp /= 10;
}
return num;
}
};
828. 字模式
给定一个模式
和一个字符串str
,查找str
是否遵循相同的模式。
这里遵循的意思是一个完整的匹配,在一个字母的模式
和一个非空的单词str
之间有一个双向连接的模式对应。
样例
给定模式= "abba"
, str = "dog cat cat dog"
,返回true
。给定模式= "abba"
, str = "dog cat cat fish"
,返回false
。
给定模式= "aaaa"
, str = "dog cat cat dog"
,返回false
。给定模式= "abba"
, str = "dog dog dog dog"
,返回false
。
注意事项
您可以假设模式
只包含小写字母,而str
包含由单个空间分隔的小写字母。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param pattern: a string, denote pattern string
* @param str: a string, denote matching string
* @return: an boolean, denote whether the pattern string and the matching string match or not
*/
bool wordPattern(string &pattern, string &str) {
// write your code here
map<char,int>p1;
map<string,int>p2;
int i=0;
int n=pattern.size();
istringstream in(str);
for(string word;in>>word;i++)
{
if(i==n||p1[pattern[i]]!=p2[word])
return false;
p1[pattern[i]]=p2[word]=i+1;
}
return true;
}
};
888. 有效单词词广场
给定一个单词序列,检查它是否构成一个有效单词广场。
一个有效的单词广场满足:如果第k行和第k列读取相同的字符串,并且0≤k<max(numRows numColumns)
。
样例
给定
[
"abcd",
"bnrt",
"crmy",
"dtye"
]
返回 true
解释:
第一行和第一列都是“abcd”。
第二行和第二列都是“bnrt”。
第三行和第三列都是“crmy”。
第四行和第四列都是“dtye”。
因此,这是一个有效的单词广场.
给定
[
"abcd",
"bnrt",
"crm",
"dt"
]
返回 true
解释:
第一行和第一列都是“abcd”。
第二行和第二列都是“bnrt”。
第三行和第三列都是“crm”。
第四行和第四列都是“dt”。
因此,这是一个有效的单词广场.
给定
[
"ball",
"area",
"read",
"lady"
]
返回 false
解释:
第三行是 "read" 但是第三列是 "lead".
因此,这不是一个有效的单词广场.
注意事项
给定的单词数量至少为1,且不超过500
。
单词长度至少为1,不超过500
。
每个单词只包含小写英文字母a-z
。
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param words: a list of string
* @return: a boolean
*/
bool validWordSquare(vector<string> &words) {
// Write your code here
for(int i = 0; i<words.size(); i++)
for(int j = i; j<words[0].size(); j++)
if(words[i][j] != words[j][i])
return false;
return true;
}
};
914. 翻转游戏
翻转游戏:给定一个只包含两种字符的字符串:+
和-
,你和你的小伙伴轮流翻转"++"
变成"--"
。当一个人无法采取行动时游戏结束,另一个人将是赢家。
编写一个函数,计算字符串在一次有效移动后的所有可能状态。
样例
给定 s = "++++"
, 在一次有效移动后,它会变成下列状态之一:
[
"--++",
"+--+",
"++--"
]
如果无法移动,则返回一个空列表[]
class Solution {
public:
/**
* @param s: the given string
* @return: all the possible states of the string after one valid move
*/
vector<string> generatePossibleNextMoves(string &s) {
// write your code here
vector<string> result;
if(s.size() == 0) return result;
for(int i = 0; i<s.size()-1; i++)
{
if(s[i] == '+'&&s[i+1] == '+')
{
string s1 = s;
s1[i] = '-';
s1[i+1] = '-';
result.push_back(s1);
}
}
return result;
}
};
1017. Similar RGB Color
In the following, every capital letter represents some hexadecimal digit from 0
to f
.
The red-green-blue color "#AABBCC"
can be written as "#ABC"
in shorthand. For example, "#15c"
is shorthand for the color "#1155cc"
.
Now, say the similarity between two colors "#ABCDEF"
and "#UVWXYZ"
is -(AB - UV)^2 - (CD - WX)^2 - (EF - YZ)^2
.
Given the color "#ABCDEF"
, return a 7 character color that is most similar to #ABCDEF
, and has a shorthand (that is, it can be represented as some "#XYZ"
)
样例
Input: color = "#09f166"
Output: "#11ee66"
Explanation:
The similarity is -(0x09 - 0x11)^2 -(0xf1 - 0xee)^2 - (0x66 - 0x66)^2 = -64 -9 -0 = -73.
This is the highest among any shorthand color.
注意事项
color
is a string of length7
.color
is a valid RGB color: fori > 0
,color[i]
is a hexadecimal digit from0
tof
- Any answer which has the same (highest) similarity as the best answer will be accepted.
- All inputs and outputs should use lowercase letters, and the output is 7 characters.
输入测试数据 (每行一个参数)
class Solution {
public:
string similarRGB(string color) {
for (int i = 1; i < 7; i += 2) {
int num = stoi(color.substr(i, 2), nullptr, 16);
int idx = num / 17 + (num % 17 > 8 ? 1 : 0);
color[i] = color[i + 1] = (idx > 9) ? (idx - 10 + 'a') : (idx + '0');
}
return color;
}
};
1032. Letter Case Permutation
Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create.
样例
Input: S = "a1b2"
Output: ["a1b2", "a1B2", "A1b2", "A1B2"]
Input: S = "3z4"
Output: ["3z4", "3Z4"]
Input: S = "12345"
Output: ["12345"]
注意事项
S will be a string with length at most 12.
S will consist only of letters or digits
class Solution {
public:
vector<string> letterCasePermutation(string S) {
vector<string> ans;
dfs(S, 0, ans);
return ans;
}
private:
void dfs(string& S, int s, vector<string>& ans) {
if (s == S.length()) {
ans.push_back(S);
return;
}
dfs(S, s + 1, ans);
if (!isalpha(S[s])) return;
S[s] ^= (1 << 5);
dfs(S, s + 1, ans);
S[s] ^= (1 << 5);
}
};
1042. Toeplitz Matrix
A matrix is Toeplitz if every diagonal from top-left to bottom-right has the same element.
Now given an M x N
matrix, return True
if and only if the matrix is Toeplitz.
样例
Example 1:
Input: matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
Output: True
Explanation:
1234
5123
9512
In the above grid, the diagonals are "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]", and in each diagonal all elements are the same, so the answer is True.
Example 2:
Input: matrix = [[1,2],[2,2]]
Output: False
Explanation:
The diagonal "[1, 2]" has different elements.
注意事项
matrix
will be a 2D array of integers.matrix
will have a number of rows and columns in range[1, 20]
.matrix[i][j]
will be integers in range[0, 99]
.
输入测试数据 (每行一个参数)
class Solution {
public:
bool isToeplitzMatrix(vector<vector<int>> &matrix) {
int m = matrix.size();
int n = matrix[0].size();
for (int i = 0; i < m - 1; i++) {
for (int j = 0; j < n - 1; j++) {
if (matrix[i][j] != matrix[i + 1][j + 1])
return false;
}
}
return true;
}
};
1046. Prime Number of Set Bits in Binary Representation
Given two integers L
and R
, find the count of numbers in the range [L, R]
(inclusive) having a prime number of set bits in their binary representation.
(Recall that the number of set bits an integer has is the number of 1
s present when written in binary. For example, 21
written in binary is 10101
which has 3 set bits. Also, 1 is not a prime.)
样例
Example 1:
Input: L = 6, R = 10
Output: 4
Explanation:
6 -> 110 (2 set bits, 2 is prime)
7 -> 111 (3 set bits, 3 is prime)
9 -> 1001 (2 set bits , 2 is prime)
10->1010 (2 set bits , 2 is prime)
Example 2:
Input: L = 10, R = 15
Output: 5
Explanation:
10 -> 1010 (2 set bits, 2 is prime)
11 -> 1011 (3 set bits, 3 is prime)
12 -> 1100 (2 set bits, 2 is prime)
13 -> 1101 (3 set bits, 3 is prime)
14 -> 1110 (3 set bits, 3 is prime)
15 -> 1111 (4 set bits, 4 is not prime)
注意事项
1.L
, R
will be integers L <= R
in the range [1, 10^6]
.
2.R - L
will be at most 10000
.
class Solution {
public:
int countPrimeSetBits(int L, int R) {
unordered_set<int> p = {2,3,5,7,11,13,17,19};
int res = 0;
for (int i = L; i <= R; ++i) {
int n = i, count = 0;
while (n) {
n = n & (n-1);
count ++;
}
if (p.count(count)) res ++;
}
return res;
}
};
1319. Contains Duplicate II
Given an array
of integers and an integer k
, find out whether there are two distinct indices i
and j
in the array such that nums[i] = nums[j]
and the absolute difference between i
and j
is at most k
.
样例
Given nums = [1,2,1]
, k = 0
, return false
.
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param nums: the given array
* @param k: the given number
* @return: whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k
*/
bool containsNearbyDuplicate(vector<int> &nums, int k) {
// Write your code here
std::unordered_map<int, int> m;
for (int i = 0; i < nums.size(); ++i) {
if (m.find(nums[i]) != m.end() && i - m[nums[i]] <= k) return true;
else m[nums[i]] = i;
}
return false;
}
};
1347. 尾随零
给定一个整数n
,返回n!
(n的阶乘)的尾随零的个数。
注意事项
您的解法时间复杂度应为对数级别。
class Solution {
public:
/**
* @param n: a integer
* @return: return a integer
*/
int trailingZeroes(int n) {
// write your code here
int ret = 0;
while(n)
{
ret += n/5;
n /= 5;
}
return ret;
}
};
1350. Excel表列标题
给定一个正整数,返回相应的列标题,如Excel表中所示。
样例
1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB
输入测试数据 (每行一个参数)
class Solution {
public:
/**
* @param n: a integer
* @return: return a string
*/
string convertToTitle(int n) {
// write your code here
string excel;
while(n > 0)
{
excel = char((n-1) % 26 + 65) + excel;
n = (n -1) / 26;
}
return excel;
}
};