问题01 数组中出现次数超过一半的数字
对于一个数组超过一半的数字就是众数,直接摩尔投票方法,其他的方法都是渣渣。
参考这个博客找出数组中出现次数超过一半的数+ 寻找众数 + 摩尔投票法
问题02 最小的k个数
这道题和求第k小的数的做法是一样的,直接快排的思想去做即可。
其实还可以使用堆来做
问题03 连续子数组的最大和
典型的动态规划DP问题,直接做吧!
int maxSubArray(int A[], int n) {
int curSum = 0;
int maxSum = A[0];
for(int j = 0; j < n; j++) {
if(curSum >= 0) {
curSum += A[j];
}
else {
curSum = A[j];
}
if(curSum > maxSum) {
maxSum = curSum;
}
}
return maxSum;
}
问题04 从1到n整数中1出现的次数
参考这个链接leetcode 233. Number of Digit One 从1到n的数组中出现数字1的数量 + 寻找规律,公式计算
问题05 把数组排成最小的数
这道题其实是希望我们能找到一个排序规则,根据这个规则排出来的数组能排成一个最小的数字。要确定排序规则,就得比较两个数字,也就是给出两个数字m和n,我们需要确定一个规则m和n哪个更大,而不是仅仅只是比较这两个数字的数值哪个更大。
这道题真的很棒!!!
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
bool cmp(int a, int b)
{
string ab = to_string(a) + to_string(b);
string ba = to_string(b) + to_string(a);
return ab < ba;
}
class Solution
{
public:
string PrintMinNumber(vector<int> n)
{
sort(n.begin(), n.end(), cmp);
string res = "";
for (int i : n)
res += to_string(i);
return res;
}
};
问题06 丑数
我就喜欢下面的做法,很棒,虽然不是那么的高效。
建议和leetcode 263. Ugly Number 丑数、leetcode 313. Super Ugly Number 超级丑数和leetcode 264. Ugly Number II 计算第K个丑数
问题07 第一次只出现一次的字符
直接使用Map统计即可
问题08 数组中的逆序对
最笨的方法就是暴力遍历,复杂度是O(n),但是又更加快的方法,这个急速使用归并排序,再归并的时候完成逆序对的统计。
将归并排序思想应用到题目中,假设我们将数组划分为两部分,左边数组有leftNum个逆序对,右边有rightNum个逆序对,那么剩余的逆序对必然是一个数出现在左边部分,一个数出现在右边部分,并且满足出现左边部分的数 a[i] > a[j]。由于左右部分依然排序,所以每当出现array[left]>array[right],必然会增加right-mid个逆序对。
代码如下:
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
class Solution
{
public:
int MMD = 1000000007;
int mergeSort(vector<int>& a, vector<int>& tmp, int beg, int end)
{
if (beg >= end)
return 0;
else
{
int mid = (end - beg) / 2 + beg;
long long left = (mergeSort(a, tmp, beg, mid)) % MMD;
long long right = (mergeSort(a, tmp, mid + 1, end)) % MMD;
long long count = 0;
int i = beg, j = mid + 1, k = beg;
while (i <= mid && j <= end)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
{
tmp[k++] = a[j++];
count += (mid - i + 1);
}
}
while (i <= mid)
tmp[k++] = a[i++];
while (j <= end)
tmp[k++] = a[j++];
for (int i = beg; i <= end; i++)
a[i] = tmp[i];
long long res = (left + right + count) % MMD;
return (int)res;
}
}
int InversePairs(vector<int> a)
{
vector<int> tmp(a);
return mergeSort(a, tmp, 0, a.size() - 1);
}
};
问题09 两个链表的第一个公共节点
思路很简单,就是先统计链表A和B的长度,假设分别是m和n,假如m>n,那么设两个遍历指针i和j,那么i像走(m-n)步,然后i和j就一起走,知道遇到公共节点。
其实还有一个更加简单的方法:遍历链表A,并把指针存入set之中,然后遍历B,那么就可以得到第一个公共节点的指针。