牛客剑指offer刷题记录(七)
来源:互联网 发布:淘宝店铺怎么打开 编辑:程序博客网 时间:2024/05/21 11:05
数组中的逆序对
算法导论上应该有这样的课后题。
归并的思路,假设f(i,j)表示数组i到j的逆序对数,那么有:
其中s(i,j,k)表示逆序对
由于归并排序,我么得到两个有序的子数组
因此每次只需计算
在代码中,由于归并时重置了索引,L和R都是从0开始,因此,当出现逆序时
#include <iostream>#include <vector>using namespace std;class Solution {private: int count; void MergeSort(vector<int>&a, int p, int r) { if (p < r) { int q = p + (r - p) / 2; MergeSort(a, p, q); MergeSort(a, q + 1, r); Merge(a, p, q, r); } } void Merge(vector<int>&a, int p, int q, int r) { int n1 = q - p + 1; int n2 = r - q; vector<int>L(n1 + 1); vector<int>R(n2 + 1); L[n1] = numeric_limits<int>::max(); R[n2] = numeric_limits<int>::max(); for (int i = 0; i < n1; ++i) L[i] = a[p + i]; for (int i = 0; i < n2; ++i) R[i] = a[q + i + 1]; int i = 0; int j = 0; for (int k = p; k <= r; ++k) { if (L[i] <= R[j]) a[k] = L[i++]; else { a[k] = R[j++]; count += (q - i + 1 - p); if(count>1000000007) count%=1000000007; } } }public: int InversePairs(vector<int> data) { vector<int>a; a.swap(data); count = 0; MergeSort(a, 0, a.size() - 1); return count; }};
两个链表的第一个公共节点
两个链表最终汇聚成一股,节点串成Y字型。
class Solution {public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { ListNode*pa=pHead1; ListNode*pb=pHead2; while(pa!=pb){ pa=pa?pa->next:pHead2; pb=pb?pb->next:pHead1; } return pa; }};
数字在排序数组中出现的次数
统计个数就是hash,这里条件给定了排序数组,可以不必额外的空间了。用二分找到上下界即可。
由于上下界算法查找得到的是开区间,因此要对特殊情况,例如[6,6,6] 6这种情况进行处理。
class Solution {private: int lower(const vector<int>&a, const int &k) { if (k <= a[0]) return -1; int l = 0; int r = a.size() - 1; int m = l + (r - l+1) / 2; while (l < r) { if (a[m] < k) l = m; else r = m - 1; m = l + (r - l + 1) / 2; } return m; } int upper(const vector<int>&a, const int &k) { if (k >= a[a.size() - 1]) return a.size(); int l = 0; int r = a.size() - 1; int m = l + (r - l) / 2; while (l < r) { if (a[m] > k) r = m; else l = m + 1; m = l + (r - l) / 2; } return m; }public: int GetNumberOfK(vector<int> data, int k) { if (data.size() == 0) return 0; vector<int>a; a.swap(data); int l = lower(a, k); int r = upper(a, k); return r - l - 1; }};
二叉树的深度
广度优先搜索和深度优先搜索都可以做。
广度优先搜索,求出层数即可:
class Solution {private: int count; void bfs(TreeNode * root) { queue<TreeNode *>q; q.push(root); while (!q.empty()) { int len = q.size(); ++count; while (len--) { TreeNode * p = q.front(); q.pop(); if (p->left != nullptr) q.push(p->left); if (p->right != nullptr) q.push(p->right); } } }public: int TreeDepth(TreeNode* pRoot) { if(pRoot==nullptr) return 0; count = 0; bfs(pRoot); return count; }};
深度优先搜索是分别递归左右子树,得到左右子树的深度,然后左右子树深度选较大者加一,表示加上根节点以后树的深度。
class Solution {private: int dfs(TreeNode *root) { if (root == nullptr) return 0; int l = dfs(root->left); int r = dfs(root->right); return max(l, r) + 1; }public: int TreeDepth(TreeNode* pRoot) { return dfs(pRoot); }};
数组中只出现1一次的两个数字
除了出现1次的两个数字,其他数字出现2次。
相同的数字异或为0,这样,遍历数组两两异或将得到一个结果,这个结果肯定是一个非0的数,这个数是由数组唯2出现一次的数得来,找到这个数的二进制位第一个不为0的位,将这个数组划分为两个子数组,就能分别找到这两个数。
总体来说就四步:
step1:遍历数组,两两异或得到num1和num2异或的结果tmp
step2:找到tmp的二进制位中第一个出现的1 bit位idx
step3:根据这个idx位是否为1将原数组划分为两个子数组
step4:两个子数组分别做step1操作,得到的结果为num1和num2
class Solution {public: void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) { int tmp = 0; //step 1 for (auto i : data) tmp ^= i; //step 2 int idx = 0; while ((tmp & 1) == 0) { tmp >>= 1; ++idx; } //step 3 vector<int>v1; vector<int>v2; v1.reserve(data.size()); v2.reserve(data.size()); for (auto i : data) { if (((i >> idx) & 1) == 1) v1.push_back(i); else v2.push_back(i); } //step 4 *num1 = 0; for (auto i : v1) *num1 ^= i; *num2 = 0; for (auto i : v2) *num2 ^= i; }};
- 牛客剑指offer刷题记录(七)
- 牛客剑指offer刷题记录(一)
- 牛客剑指offer刷题记录(二)
- 牛客剑指offer刷题记录(三)
- 牛客剑指offer刷题记录(四)
- 牛客剑指offer刷题记录(五)
- 牛客剑指offer刷题记录(六)
- C语言学习笔记(七)---一些刷题记录
- 剑指offer刷题记录1
- 剑指offer刷题记录2
- 剑指offer 日常刷题记录
- 每周刷题记录(持续更新)
- OI刷题记录
- OI刷题记录~
- leetcode刷题记录
- 刷题记录
- 6.22刷题记录
- 7.26-刷题记录
- Day7
- Restructuring Company
- fx60vm+gtx1060+Ubuntu 16.04+tensorflow(gpu)环境搭建
- excel 排序
- Servlet的5种方式实现表单提交,后台获取表单数据
- 牛客剑指offer刷题记录(七)
- ImageLoadAsyncTask.java11
- vagrant/util/io.rb:32:in `encode': incomplete "\xB7" on GBK (Encoding::InvalidByteSequenceError)
- 1的个数
- StreamTools.java11
- 根据点画多边形
- C# 对try catch和void的简单理解
- 最短路的神奇用法 bzoj1550 避开怪兽
- HealthInfo.java11