1、数组中出现次数超过一半的数字
本题考点: 数组使用,简单算法的设计 牛客链接
题目描述:
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
数据范围:50000n≤50000,数组中元素的值 0≤val≤10000
要求:空间复杂度:O(1),时间复杂度 O(n)
输入描述:
保证数组输入非空,且保证有解
解题思路:
思路一:定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数
思路二:排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求
思路三:目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的数就是该数字。将数组遍历一遍统计一下数字出现次数进行最终判断。
代码
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
//方法一:哈希法
// unordered_map<int, int> ump;
// for(auto& num : numbers)
// {
// ump[num]++;
// }
// int ret = 0;
// for(auto& up : ump)
// {
// if(up.second > (numbers.size() / 2))
// ret = up.first;
// }
// return ret;
//方法二:排序法
//先排序找到中间值,在统计中间值的次数
// sort(numbers.begin(), numbers.end());
// int mid = numbers[numbers.size() / 2];
// int count = 0;
// for(int num : numbers)
// {
// if(num == mid)
// ++count;
// }
// if(count > (numbers.size() / 2))
// return mid;
// return 0;
//方法三: 若是有超过一半的数字,那么遍历一遍一次去掉两个不相同的数字,
//剩下的数字则可能是要找的数字,通过遍历统计次数来判别
int number = numbers[0]; //可以采取不同的数量进行抵消的思路
int count = 1;
for(int i = 1; i < numbers.size(); i++)
{
if(count == 0) //如果当前times是0,说明之前的不同抵消完了
{
number = numbers[i];
count = 1;
}
else if(number == numbers[i])
{
count++;
}
else
{
count--;
}
}
count = 0;
for(int num : numbers)
{
if(num == number)
++count;
}
return count > numbers.size() / 2 ? number : 0;
}
};
2、替换空格
本题考点: 字符串相关,特性观察,临界条件处理 牛客链接
题目描述:
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
解题思路:
这题比较简单,题中是一个空格替换成三个字符,所以替换完成后字符串一定会变成,题中给我们传过来的是一个指针,所以不用担心扩容的问题。故我们可以先统计出空格的个数算出最后位置的下标,从后向前一个个挪动就可以了。
代码:
class Solution {
public:
void replaceSpace(char *str,int length) {
if(nullptr == str || length == 0)
return;
int count = 0;
for(int i = 0; str[i] != '\0'; i++)
{
if(str[i] == ' ')
count++;
}
cout << count << endl;
int old_index = length - 1;
int new_index = length + 2 * count - 1;
while(old_index >= 0 || new_index >= 0)
{
if(str[old_index] == ' ')
{
str[new_index--] = '0';
str[new_index--] = '2';
str[new_index--] = '%';
old_index--;
}
else
{
str[new_index] = str[old_index];
old_index--;
new_index--;
}
}
}
};
3、从尾到头打印链表
本题考点: 链表相关,多结构混合使用,递归。牛客链接
题目描述:
输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
如输入{1,2,3}的链表如图:
返回一个数组为[3,2,1]
0 <= 链表长度 <= 10000
示例1
输入: {1,2,3}
返回值: [3,2,1]
解题思路:
这道题整体解决思路很多,可以使用stack,可以将数据保存数组后逆序数组,也可以递归,前两种比较简单,我们使用递归来写一下:
代码:
class Solution {
public:
void _printListFromTailToHead(ListNode* head, vector<int>& v)
{
if(head == nullptr)
return;
_printListFromTailToHead(head->next, v);
v.push_back(head->val);
}
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> v;
_printListFromTailToHead(head, v);
return v;
}
};
4、重建二叉树
本题考点: 遍历理解,递归 牛客链接
题目描述:
解题思路:
代码:
class Solution {
public:
TreeNode* _reConstructBinaryTree(vector<int> pre,vector<int> vin, int& index, int left, int right)
{
//返回条件
if(left > right)
return nullptr;
TreeNode* root = new TreeNode(pre[index]); //构建根
int rooti = left;
while(rooti <= right)
{
if(pre[index] == vin[rooti])
break;
else
++rooti;
}
index++;
root->left = _reConstructBinaryTree(pre, vin, index, left, rooti - 1);
root->right = _reConstructBinaryTree(pre, vin, index, rooti + 1, right);
return root;
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.empty() || vin.empty())
return nullptr;
int index = 0;
return _reConstructBinaryTree(pre, vin, index, 0, pre.size() - 1);
}
};