剑指offer读书笔记第五章,优化时间和空间效率
问题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,那么就可以得到第一个公共节点的指针。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhibhjbc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22 -
excel打印预览压线压字怎么办
PHP中文网 06-22