剑指offer 试题51~60
来源:互联网 发布:美国windows vps 编辑:程序博客网 时间:2024/06/05 13:23
试题51:数组中的逆序对
在归并排序的过程中统计逆序对,经典题目了,也可以用树状数组,这里就不写了
class Solution {public: int InversePairs(vector<int> data) { if(data.size() == 0) return 0; vector<int> temp(data.size()); return mergeSort(data, temp, 0, data.size()-1); }private: int mergeSort(vector<int> &data, vector<int> &temp, int l, int r) { int ans = 0; if(l < r) { int mid = (l + r) >> 1; ans += mergeSort(data, temp, l, mid); ans %= 1000000007; ans += mergeSort(data, temp, mid+1, r); ans %= 1000000007; ans += Merge(data, temp, l, r, mid); ans %= 1000000007; } return ans; } int Merge(vector<int> &data, vector<int> &temp, int l, int r, int mid) { int index = l, index1 = l, index2 = mid+1; int ans = 0; while(index1 <= mid && index2 <= r) { if(data[index1] <= data[index2]) temp[index++] = data[index1++]; else { temp[index++] = data[index2++]; ans = (ans + mid - index1 + 1) % 1000000007; } } while(index1 <= mid) temp[index++] = data[index1++]; while(index2 <= r) temp[index++] = data[index2++]; for(int i = l; i <= r; ++i) data[i] = temp[i]; return ans; }};
试题52:两个链表的第一个公共节点
方法一:
把两个链表的节点分别压入栈中,根据栈的性质,栈顶即链表的尾部,让两个栈同时弹出节点,直到两个栈弹出的节点不相等,那么最后一次相等的节点就是两个链表的公共节点
class Solution {public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { if(pHead1 == nullptr || pHead2 == nullptr) return nullptr; stack<ListNode*> stk1, stk2; inStack(pHead1, stk1); inStack(pHead2, stk2); ListNode *ans = nullptr; while(!stk1.empty() && !stk2.empty() && stk1.top() == stk2.top()) { ans = stk1.top(); stk1.pop(); stk2.pop(); } return ans; }private: void inStack(ListNode *pHead, stack<ListNode*> &stk) { while(pHead != nullptr) { stk.emplace(pHead); pHead = pHead->next; } }};
方法二:
先计算出两个链表的长度,让较长的链表先往前走一段距离,使两者距离链表尾部的距离相等,然后两者一起向尾部走,直到走到两者相等,此时这个节点就是两个链表的第一个公共节点
class Solution {public: ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { if(pHead1 == nullptr || pHead2 == nullptr) return nullptr; int len1 = countLen(pHead1); int len2 = countLen(pHead2); ListNode *ans = nullptr; ListNode *curNode1 = pHead1, *curNode2 = pHead2; if(len1 > len2) { while(len1-- > len2) curNode1 = curNode1->next; } else if(len1 < len2) { while(len2-- > len1) curNode2 = curNode2->next; } while(curNode1 != nullptr && curNode2 != nullptr && curNode1 != curNode2) { curNode1 = curNode1->next; curNode2 = curNode2->next; } if(curNode1 != nullptr && curNode2 != nullptr) ans = curNode1; return ans; }private: int countLen(ListNode *pHead) { int len = 0; while(pHead != nullptr) { ++len; pHead = pHead->next; } return len; }};
试题53:在排序数组中查找数字
数组既然是有序的,那么二分查找找到数字的第一个位置,再二分查找找到第一个大于此数字的位置,两个位置之间都是此数字,两个位置作差就是答案
class Solution {public: int GetNumberOfK(vector<int> data ,int k) { return upper_bound(data.begin(), data.end(), k) - lower_bound(data.begin(), data.end(), k); }};
0~n-1中缺失的数字
class Solution {public: int GetNumberOfDefect(vector<int> data) { if(data.size() == 0) return -1; int ans = -1; int l = 0, r= data.size() - 1; while(l <= r) { int mid = (l + r) >> 1; if(data[mid] != mid) ans = mid, r = mid - 1; else l = mid + 1; } if(ans == -1) ans = data.size(); return ans; }};
数组中数值和下标相等的元素
class Solution {public: int GetNumber(vector<int> data) { int l = 0, r = data.size() - 1; int ans = -1; while(l <= r) { int mid = (l + r) >> 1; if(data[mid] == mid) { ans = mid; break; } else if(data[mid] < mid) l = mid + 1; else r = mid - 1; } return ans; }};
试题54:二叉搜索树的第k大节点
二叉搜索树的中序遍历就是有序的,那么只需要中序遍历二叉搜索树,并记录当前遍历的节点是中序遍历的第几个节点,遍历到第k个的时候就是答案
class Solution {public: TreeNode* KthNode(TreeNode* pRoot, int k) { if(pRoot == nullptr || k <= 0) return nullptr; return _KthNode(pRoot, k); }private: TreeNode* _KthNode(TreeNode *pRoot, int &k) { TreeNode *ans = nullptr; if(pRoot->left != nullptr) ans = _KthNode(pRoot->left, k); if(ans == nullptr) { if(--k == 0) ans = pRoot; } if(ans == nullptr && pRoot->right != nullptr) ans = _KthNode(pRoot->right, k); return ans; }};
试题55:二叉树的深度
用递归函数,用一个变量记录当前节点到根节点的距离,最大距离就是答案。
class Solution {public: int TreeDepth(TreeNode* pRoot) { return _TreeDepth(pRoot, 0); }private: int _TreeDepth(TreeNode *pRoot, int dep) { if(pRoot == nullptr) return dep; return max(_TreeDepth(pRoot->left, dep+1), _TreeDepth(pRoot->right, dep+1)); }};
平衡二叉树
在求树的深度的过程中,检查其左右子树深度之差是不是不超过1即可
class Solution {public: bool IsBalanced_Solution(TreeNode* pRoot) { bool IsBalanced = true; check(pRoot, 0, IsBalanced); return IsBalanced; }private: int check(TreeNode *pRoot, int dep, bool &IsBalanced) { if(pRoot == nullptr) return dep; int leftDep = check(pRoot->left, dep+1, IsBalanced); int rightDep = check(pRoot->right, dep+1, IsBalanced); if(abs(leftDep - rightDep) > 1) IsBalanced = false; return max(leftDep, rightDep); }};
试题56:数组中只出现一次的两个数字
数组只有两个数字各出现一次,其余数字都出现两次。
按照剑指offer上写的,确实巧妙
class Solution {public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { int xor_sum = 0; for(int i = 0; i < data.size(); ++i) xor_sum ^= data[i]; int num = 0; while(!(xor_sum & (1<<num))) ++num; vector<int> data1, data2; for(int i = 0; i < data.size(); ++i) if(data[i] & (1<<num)) data1.emplace_back(data[i]); else data2.emplace_back(data[i]); *num1 = 0; for(int i = 0; i < data1.size(); ++i) *num1 = *num1 ^ data1[i]; *num2 = 0; for(int i = 0; i < data2.size(); ++i) *num2 = *num2 ^ data2[i]; }};
数组中唯一只出现一次的数字
数组中有一个数字只出现一次,其余数字都出现三次
求出每个数字的二进制表示,并统计每个二进制位上有多少个二进制1,然后把每个二进制位上1的个数取余3,剩下的就是只出现一次的那个数字的二进制表示
class Solution {public: int FindNumsAppearOnce(vector<int> data) { const int N = 40; int bit[N]; memset(bit, 0, sizeof bit); for(int i = 0; i < data.size(); ++i) { for(int j = 0; j < 32; ++j) if(data[i] & (1<<j)) ++bit[j]; } int ans = 0; for(int i = 31; i >= 0; --i) { ans <<= 1; ans += bit[i] % 3; } return ans; }};
试题57:和为s的数字
class Solution {public: vector<int> FindNumbersWithSum(vector<int> array,int sum) { vector<int> ans; if(array.size() < 2) return ans; int l = 0, r = array.size() - 1; while(l < r) { if(array[l] + array[r] == sum) { ans.emplace_back(array[l]); ans.emplace_back(array[r]); break; } else if(array[l] + array[r] > sum) --r; else ++l; } return ans; }};
和为s的连续正数序列
class Solution {public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int>> ans; if(sum <= 0) return ans; int temp = 0, index_l = 1, index_r = 1; while(index_r < sum) { temp += index_r; index_r++; while(temp > sum) { temp -= index_l; ++index_l; } if(temp == sum) { vector<int> vec; for(int i = index_l; i < index_r; ++i) vec.emplace_back(i); ans.emplace_back(vec); } } return ans; }};
试题58:翻转单词顺序
class Solution {public: string ReverseSentence(string str) { if(str.size() == 0) return str; reverse(str.begin(), str.end()); int l = 0, r = 0; while(r < str.size()) { while(r < str.size() && str[r] == ' ') ++r; l = r; while(r < str.size() && str[r] != ' ') ++r; for(int i = l, j = r-1; i < j; ++i, --j) swap(str[i], str[j]); } return str; }};
左旋转字符串
class Solution {public: string LeftRotateString(string str, int n) { reverse(str.begin(), str.end()); int index = str.size() - n; for(int i = 0, j = index-1; i < j; ++i, --j) swap(str[i], str[j]); for(int i = index, j = str.size()-1; i < j; ++i, --j) swap(str[i], str[j]); return str; }};
试题59:滑动窗口的最大值
class Solution {public: vector<int> maxInWindows(const vector<int>& num, unsigned int size) { deque<int> que; vector<int> ans; if(num.size() < size) return ans; for(int i = 0; i < num.size(); ++i) { while(!que.empty() && num[que.back()] < num[i]) que.pop_back(); que.push_back(i); if(i >= size-1) { while(! que.empty() && que.front() < i - size + 1) que.pop_front(); ans.emplace_back(num[que.front()]); } } return ans; }};
试题60:n个骰子的点数
牛客上没有这题,剑指offer上讲的很详细,不写了
阅读全文
0 0
- 剑指offer 试题51~60
- 剑指offer面试题51
- 剑指offer 面试题51 java实现
- 剑指Offer试题总结
- 剑指offer 面试题
- 剑指offer面试题
- 剑指offer面试题总结
- 剑指offer面试题06
- 剑指offer面试题 04
- 剑指offer 面试题07
- 剑指offer面试题08
- 剑指offer面试题42
- 剑指offer面试题1
- 剑指offer面试题3
- 剑指offer面试题4
- 剑指offer面试题5
- 剑指offer面试题6
- 剑指offer面试题7
- Deep Learning(深度学习)学习笔记整理系列之(三)
- jNI callback
- python 基础(一)变量数据类型
- Bootstrap(二十七)
- 校oj10532: 生成字符串(dp,最优状态转移)
- 剑指offer 试题51~60
- POJ-2239 Selecting Courses(二分图最大匹配)
- 关于C++、PHP和Swoole
- 软件工程:“银弹”论
- ci框架&框架设计思路
- 【随笔】Oct, 19, 2017
- iOS简单工厂模式
- 清除进程
- 剑指offer——面试题8:旋转数组的最小数值