1--数组中的逆序对(51)
主要思路:
基于归并排序,视频讲解参考:数组中的逆序对
#include <iostream>
#include <vector>
class Solution {
public:
int reversePairs(std::vector<int>& nums) {
if(nums.size() <= 1) return 0;
return mergeSort(nums, 0, nums.size() - 1);
}
int mergeSort(std::vector<int>& nums, int left, int right){
if(left >= right) return 0;
int mid = left + (right - left) / 2;
int count1 = mergeSort(nums, left, mid);
int count2 = mergeSort(nums, mid+1, right);
int count3 = merge(nums, left, mid, mid+1, right);
return count1 + count2 + count3;
}
int merge(std::vector<int>& nums, int l1, int r1, int l2, int r2){
std::vector<int> tmp;
int count = 0;
int i = l1, j = l2;
while(i <= r1 && j <= r2){
if(nums[i] > nums[j]){
count = count + l2 - i;
tmp.push_back(nums[j]);
j++;
}
else{
tmp.push_back(nums[i]);
i++;
}
}
while(i <= r1){
tmp.push_back(nums[i]);
i++;
}
while(j <= r2){
tmp.push_back(nums[j]);
j++;
}
for(int i = l1, k = 0; i <= r2; i++, k++){
nums[i] = tmp[k];
}
return count;
}
};
int main(int argc, char *argv[]){
std::vector<int> test = {7, 5, 6, 4};
Solution S1;
int Res = S1.reversePairs(test);
std::cout << Res << std::endl;
return 0;
}
2--两个链表的第一个公共结点(52)
主要思路:
两个指针分别指向 A 链表和 B 链表,先让两个指针走完自己的链表,再去走别人的链表,这样两个指针走的总路程是相等的;因此两个指针最终肯定会相遇,相遇的地点要么在结尾(不相交),要么在共有的结点中(相交),只需找到第一个共有的结点即可,此时两个指针指向同一个结点; (所以题目都可以这么浪漫的吗。。。 2023 07 20)
#include <iostream>
#include <vector>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == NULL || headB == NULL) return NULL;
ListNode *A = headA;
ListNode *B = headB;
while(A != B){
if(A != NULL){
A = A->next; // 先走完A
}
else{
A = headB; // 再走B
}
if(B != NULL){
B = B->next; // 先走完B
}
else{
B = headA; // 再走A
}
}
return A; // 走的总路程相等,A最终肯定会和B相遇,要么在NULL(不相交),要么在第一个共同的结点(相交)
}
};
int main(int argc, char *argv[]){
ListNode *Node1 = new ListNode(4);
ListNode *Node2 = new ListNode(1);
ListNode *Node3 = new ListNode(8);
ListNode *Node4 = new ListNode(4);
ListNode *Node5 = new ListNode(5);
Node1->next = Node2;
Node2->next = Node3;
Node3->next = Node4;
Node4->next = Node5;
ListNode *Node6 = new ListNode(5);
ListNode *Node7 = new ListNode(0);
ListNode *Node8 = new ListNode(1);
Node6->next = Node7;
Node7->next = Node8;
Node6->next = Node3;
Solution S1;
ListNode *Res = S1.getIntersectionNode(Node1, Node6);
std::cout << Res->val << std::endl;
return 0;
}
3--在排序数组中查找数字 I(53-I)
主要思路:
假如数组不是有序的,可以使用哈希,哈希表 key 表示数组的元素,value表示出现的次数,最后只需查询 key 为target对应的个数即可;
#include <iostream>
#include <vector>
#include <map>
class Solution {
public:
int search(std::vector<int>& nums, int target) {
if(nums.size() == 0) return 0;
std::map<int, int> hash;
for(int i = 0; i < nums.size(); i++){
if(hash.find(nums[i]) != hash.end()) hash[nums[i]] += 1;
else hash[nums[i]] = 1;
}
if(hash.find(target) != hash.end()) return hash[target];
else return 0;
}
};
int main(int argc, char *argv[]){
std::vector<int> test = {5, 7, 7, 8, 8, 10};
int target = 8;
Solution S1;
int res = S1.search(test, target);
std::cout << res << std::endl;
return 0;
}
主要思路:
由于题目是有序的,因此使用二分法查询;
查找第一个比 target 大的数(右边界 right),查找第一个比 target 小的数(左边界 left),则与target 相同的数目为:right - left - 1;
#include <iostream>
#include <vector>
#include <map>
class Solution {
public:
int search(std::vector<int>& nums, int target) {
if(nums.size() == 0) return 0;
int i = 0, j = nums.size() - 1;
// 查找右边界
while(i <= j){
int mid = i + (j - i) / 2;
if(target < nums[mid]) j = mid - 1;
else i = mid + 1;
}
int right = i;
i = 0;
// 查找左边界
while(i <= j){
int mid = i + (j - i) / 2;
if(target <= nums[mid]) j = mid - 1;
else i = mid + 1;
}
int left = j;
return right - left - 1;
}
};
int main(int argc, char *argv[]){
std::vector<int> test = {5, 7, 7, 8, 8, 10};
int target = 8;
Solution S1;
int res = S1.search(test, target);
std::cout << res << std::endl;
return 0;
}
4--0~n-1中缺失的数字(53-II)
主要思路:
由于数组是有序的,可以使用二分法来查找缺失的数字;
当 nums[mid] == mid 时,缺失的数字肯定在右区间,执行 i = mid + 1;
否则执行 j = mid - 1,最后返回左指针即可;
#include <iostream>
#include <vector>
class Solution {
public:
int missingNumber(std::vector<int>& nums) {
int i = 0, j = nums.size() - 1;
while(i <= j){
int mid = i + (j - i) / 2;
if(nums[mid] == mid) i = mid + 1;
else j = mid - 1;
}
return i;
}
};
int main(int argc, char *argv[]){
std::vector<int> test = {0, 1};
Solution S1;
int res = S1.missingNumber(test);
std::cout << res << std::endl;
return 0;
}
5--二叉搜索树的第k大结点(54)
主要思路: