搜索插入位置(简单)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
解题:
简单的二分查找问题,由于我们知道当排序数组当中存在目标值的情况,则直接返回mid下标即可,当排序数组当中不包含目标值,此时我们可以分析得出,while循环的倒数第一次中,必定left=right,此时定位到的元素一定为第一个比target目标值大的元素,紧接着right值减一,退出while循环。故我们可以知道此时left下标对应的元素为target目标值应该插入的位置。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left <= right) {
int mid = left + ((right - left) >> 1);
if(nums[mid] == target) {
return mid;
}
else if(nums[mid] < target) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
return left;
}
};
外观数列(简单)
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
1 | 1 |
2 | 11 |
3 | 21 |
4 | 1211 |
5 | 111221 |
其中:
- 1 被读作 "one 1" ("一个一") , 即 11。
- 11 被读作 "two 1s" ("两个一"), 即 21。
- 21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
解题:
这道题其实并不难,重要的是理解题意,想起来好像在之前美团线下面试的时候被问到了这道题,当时是以一道智力题的方式给出外观数列的前五项,让我写出第六项,当时没有反应过来,现在回过头来才发觉原来正是这道外观数列题的抽象。话不多说,接下来分析这道题:外观数列其实就是重复的对上一个数进行描述的数列,我们举例来说明:
- 首先第一个数为1,该数事先给出;
- 接下来第二个数对第一个数1进行描述,1当中有1个1,因此第二个数为11;
- 接下来第三个数对第二个数11进行描述,11当中有2个1,因此第三个数为21;
- 接下来第四个数对第三个数21进行描述,21当中有1个2以及1个1,因此第四个数为1211;
- 接下来第五个数对第四个数1211进行描述,1211当中有1个1以及1个2以及2个1,因此第五个数为111221。
这下我们总算理解了题意,开始我们的代码:
class Solution {
public:
string countAndSay(int n) {
string str, res;
res = "1";
if (n == 1) return res;
for (int i = 1; i < n; ++i)
{
str = res;
res = "";
for (int j = 0; j < str.size();)
{
// c为计数器,k为当前描述数字对应下标
int c=0,k=j;
// 若k合法且str[k]重复则计数
while(k<str.size()&&str[k]==str[j])
{
++k;
++c;
}
res+=to_string(c)+str[j];
j=k;
}
}
return res;
}
};
最后一个单词的长度(简单)
给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指由字母组成,但不包含任何空格的字符串。
解题:
这道题的重点在于对于特殊情况的考虑:
- 第一种情况,"Hello World",此时返回最后一个单词World的长度5
- 第二种情况,"Hello World ",此时需要先处理尾空格后,返回最后一个单词World的长度5
分析好特殊情况后,开始编写代码:
class Solution {
public:
int lengthOfLastWord(string s) {
int last = s.size();
for(int i = s.size() - 1; i >= 0; --i)
{
if(s[i] == ' ')
last = i;
else
break;
}
int flag = 0;
for(int i = 0; i < last; ++i)
{
if(s[i] == ' ')
{
flag = i + 1;
}
}
return last - flag;
}
};
二进制求和(简单)
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1
和 0
。
解题:
反向求和,为空补0,标记进位数。
class Solution {
public:
string addBinary(string a, string b) {
string ans = "";
int ca = 0;
for(int i = a.size() - 1, j = b.size() - 1; i >= 0 || j >= 0; --i, --j)
{
int sum = ca;
sum += i >= 0 ? a[i] - '0' : 0;
sum += j >= 0 ? b[j] - '0' : 0;
ans = to_string(sum % 2) + ans;
ca = sum / 2;
}
if (ca == 1)
ans = to_string(ca) + ans;
return ans;
}
};
x的平方(简单)
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
解题:
这道题也称为牛顿法,换而言之也就是二分查找的变形问题。之前有一篇博客就是关于二分查找的,可以具体去看那篇博客。
class Solution {
public:
int mySqrt(int x) {
long left = 0, right = x/2 + 1;
while(left <= right)
{
long mid = left + ((right - left) >> 1);
if(mid * mid > x)
{
right = mid - 1;
}
else
{
if((mid == x/2 + 1) || (mid+1) * (mid+1) > x)
return mid;
else
left = mid + 1;
}
}
return -1;
}
};
爬楼梯(简单)
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
解题:
简单的推导问题,推导出公式:A[n] = A[n-1] + A[n-2]进而求解:
class Solution {
public:
int climbStairs(int n) {
if (n < 3)
return n;
const int len = n+1;
int a[len];
a[1] = 1;
a[2] = 2;
for(int i = 3; i <= n; ++i)
{
a[i] = a[i-1] + a[i-2];
}
return a[n];
}
};
删除排序链表中的重复元素(简单)
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* current = head;
while (current != nullptr && current->next != nullptr) {
if (current->next->val == current->val) {
current->next = current->next->next;
} else {
current = current->next;
}
}
return head;
}
};
相同的树(简单)
给定两个二叉树,编写一个函数来检验它们是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
解题:
递归求解即可:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p == nullptr && q == nullptr)
return true;
else if(p == nullptr || q == nullptr)
return false;
else if(p->val != q->val)
return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
};