标签:fas ast 快速 算法 using 条件 == 荷兰国旗问题 空间
通过数组相邻两个数之间的比较和位置的交换,使得关键字最小的记录如气泡一样冒出水面
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N];
void bubble_sort(int a[], int n)
{
for(int i = 0; i < n - 1; i++)
{
for(int j = n - 1; j > i; j--)
{
if(a[j] < a[j - 1]) swap(a[j], a[j - 1]);
}
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
bubble_sort(a, n);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
每次从待排序的数字中选择一个数字(基准),将其插入到数组合适的位置中。左边的数都比它小,右边都比它大。在对左右两边的元素执行相同的操作,直到整个数组有序。
容易出错的点:
26行,边界[l, j] [j + 1, r]
19行,do while循环不是if
#include <iostream>
using namespace std;
const int N = 100010;
int a[N];
int n;
void quick_sort(int a[], int l, int r)
{
//递归终止条件
if(l >= r) return ;
//选择基准
int x = a[(r + l) >> 1], i = l - 1, j = r + 1;
//将基准插入到合适的位置 双指针 i在头部 j在尾部
while(i < j)
{
//i一直往后移动,直到找到第一个大于等于x的数
do i++; while(a[i] < x);
//j一直往后移动,直到找到第一个小于等于x的数
do j--; while(a[j] > x);
//交换两个元素的位置
if(i < j) swap(a[i], a[j]);
}
//递归处理左右两边 边界问题,容易出错
quick_sort(a, l, j), quick_sort(a, j + 1, r);
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
quick_sort(a, 0, n - 1);
for(int i = 0; i < n; i++) cout <<a[i] <<" ";
cout << endl;
return 0;
}
将多个有序的数组合并到一起
容易写错的地方:
#include <iostream>
using namespace std;
const int N = 100010;
int q[N];
int a[N];
int n;
void merge_sort(int a[], int l, int r)
{
//递归终止条件
if(l >= r) return ;
//确定分界点,排序左右两边
int mid = (l + r) >> 1;
merge_sort(a, l, mid), merge_sort(a, mid + 1, r);
//合并两个有序数组
int k = 0;
//i和j分别是每个数组的起点
int i = l, j = mid + 1;
while(i <= mid && j <= r)
{
if(a[i] < a[j]) q[k++] = a[i++];
else q[k++] = a[j++];
}
//处理未排序完的
while(i <= mid) q[k++] = a[i++];
while(j <= r) q[k++] = a[j++];
//将排好序的结果放到a中
//合并的范围是从[l, r],所以将q中的数组放到a[l, r]的位置上
for(int i = l, k = 0; i <= r; i++, k++) a[i] = q[k];
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
merge_sort(a, 0, n - 1);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
每次从待排序的记录中选出关键字最小的记录,顺序放到以及那个排好序的数组的最后,直到全部排完。
#include <iostream>
using namespace std;
const int N = 100010;
int a[N];
int n;
void select_sort(int a[], int n)
{
for(int i = 0; i < n - 1; i++)
{
int k = i; // 有序区的终点
//每次挑选无序区最小的
for(int j = i + 1; j < n; j++)
if(a[k] > a[j]) k = j;
//将最小的数交换到有序区
if(k != i) swap(a[k], a[i]);
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
select_sort(a, n);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
每次将待排序中的一个记录,按照其关键字大小插入到前面已经排好序的子表的适当位置,直到全部记录插入完成为止。
#include <iostream>
using namespace std;
const int N = 100010;
int a[N];
int n;
void insert_sort(int a[], int n)
{
for(int i = 1; i < n; i++)
{
//无序区首个元素
int tmp = a[i];
int j = i - 1;
//将无序区的第一个元素插入到有序区合适的位置
while(j >= 0 && tmp < a[j]) a[j + 1] = a[j], j--;
a[j + 1] = tmp;
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
insert_sort(a, n);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
利用二分查找找出插入位置
#include <iostream>
using namespace std;
const int N = 100010;
int a[N];
int n;
void mid_insert_sort(int a[], int n)
{
for(int i = 1; i < n; i++)
{
int tmp = a[i]; //无序区第一个元素
int l = 0, r = i - 1;
//使用二分确定要插入的位置
while(l <= r)
{
int mid = (l + r) >> 1;
if(tmp < a[mid]) r = mid - 1;
else l = mid + 1;
}
//顺序移动进行插入
for(int j = i - 1; j >= r + 1; j--)
a[j + 1] = a[j];
a[r + 1] = tmp;
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
mid_insert_sort(a, n);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
const int N = 100010;
int a[N];
int n;
void shell_insert(int a[], int n)
{
int gap = n / 2;
while(gap > 0)
{
//对所有索引相距gap位置的所有元素进行排序
for(int i = gap; i < n; i++)
{
int tmp = a[i];
int j = i - gap;
while(j >= 0 && tmp < a[j])
{
a[j + gap] = a[j];
j = j - gap;
}
a[j + gap] = tmp;
j -= gap;
}
gap /= 2;
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
shell_insert(a, n);
for(int i = 0; i < n; i++) cout << a[i] << " ";
cout << endl;
return 0;
}
统计数组中每个值i出现的次数,存入数组C的第i项;根据C[i]的值,整理排序结果
题目链接:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/
class Solution {
public:
string minNumber(vector<int>& nums) {
auto compare = [](string &sa, string &sb){return sa + sb < sb + sa;};
vector<string> tmp;
for(auto n: nums) tmp.push_back(to_string(n));
sort(tmp.begin(), tmp.end(), compare);
string ans = "";
for(auto s:tmp) ans += s;
return ans;
}
};
题目链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
简直太暴力
class Solution {
public:
int reversePairs(vector<int>& nums) {
int res = 0;
for(int i = 0; i < nums.size() - 1; i++)
{
for(int j = i + 1; j < nums.size(); j++)
{
if(nums[i] > nums[j]) res++;
}
}
return res;
}
};
分治的思想
class Solution {
public:
int merge_sort(vector<int> &nums, int l, int r)
{
if(l >= r) return 0;
int mid = ( l + r) >> 1;
long long res = merge_sort(nums, l, mid) + merge_sort(nums, mid + 1, r);
int k = 0;
int i = l, j = mid + 1;
/*合并两个有序数组*/
vector<int> tmps(r - l + 1);
while(i <= mid && j <= r)
{
if(nums[i] <= nums[j]) tmps[k++] = nums[i++];
else
{
tmps[k++] = nums[j++];
//由于两个数组目前都有序,所以逆序对的个数 = 第一个数组的i之后的元素个数 mid - i + 1
res += mid - i + 1;
}
}
while(i <= mid ) tmps[k++] = nums[i++];
while(j <= r) tmps[k++] = nums[j++];
for(int i = l, k = 0; i <= r; i++, k++) nums[i] = tmps[k];
return res;
}
int reversePairs(vector<int>& nums) {
return merge_sort(nums, 0, nums.size() - 1);
}
};
题目链接:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/
class Solution {
public:
bool isStraight(vector<int>& nums) {
sort(nums.begin(), nums.end());
for(int i = 1; i < nums.size(); i++)
if(nums[i] && nums[i] == nums[i - 1])
return false;
for(auto x : nums)
if(x) return nums.back() - x <= 4;
return false;
}
};
题目链接:https://leetcode-cn.com/problems/merge-intervals/submissions/
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
//所有区间按照left排序
//比较区间的右端点r1和下一个区间l2的做端点,
//如果r1 < l2, 合并
//否则,插入数组
vector<vector<int>> res;
sort(intervals.begin(), intervals.end());
for(int i = 0; i < intervals.size(); i++)
{
int l = intervals[i][0], r = intervals[i][1];
if(!res.size() || res.back()[1] < l) res.push_back({l, r});
else res.back()[1] = max(res.back()[1], r);
}
return res;
}
};
题目链接:https://leetcode-cn.com/problems/sort-colors/
p0 0的最右边位置 p2 2的最左边 cur当前元素。
初始化: p0 = 0 p2 = n - 1 cur = 0
沿着cur遍历数组,若nums[cur] = 0,将其与nums[p0]交换;若nums[cur] = 2,将其与nums[p2]交换
时间复杂度为O(n)
空间复杂度为O(1)
class Solution {
public:
void sortColors(vector<int>& nums) {
// 对于所有 idx < p0 : nums[idx < p0] = 0
// 对于所有 idx > p2 : nums[idx > p2] = 2
// curr 是当前考虑元素的下标
int p0 = 0, cur = 0, p2 = nums.size() - 1;
while(cur <= p2)
{
if(nums[cur] == 0) swap(nums[cur++], nums[p0++]);
//因为curr左边的值已经扫描过了,所以curr要++继续扫描下一位,而与p2交换的值,curr未扫描,要停下来扫描一下,所以curr不用++。
else if(nums[cur] == 2) swap(nums[cur], nums[p2--]);
else cur++;
}
}
};
题目链接:https://leetcode-cn.com/problems/sort-list/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head || !head->next) return head;
ListNode* pre = head, *slow = head, *fast = head;
while(fast && fast->next) {
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
pre->next = nullptr;
return mergeTwoList(sortList(head), sortList(slow));
}
ListNode* mergeTwoList(ListNode* h1, ListNode* h2) {
if(!h1) return h2;
if(!h2) return h1;
if(h1->val < h2->val) {
h1->next = mergeTwoList(h1->next, h2);
return h1;
}
else {
h2->next = mergeTwoList(h1, h2->next);
return h2;
}
}
};
题目链接:https://leetcode-cn.com/problems/meeting-rooms-ii/
时间复杂度: O(nlogn)
空间复杂度: O(n)
class Solution {
public:
int minMeetingRooms(vector<vector<int>>& intervals) {
if(intervals.empty()) return 0;
int res = 0;
int len = intervals.size();
vector<int> start, end;
for(int i = 0; i < len; i++)
{
start.push_back(intervals[i][0]);
end.push_back(intervals[i][1]);
}
sort(start.begin(), start.end());
sort(end.begin(), end.end());
int st_idx = 0, end_idx = 0;
while(st_idx < len)
{
if(start[st_idx] >= end[end_idx])
{
res -= 1;
end_idx += 1;
}
res += 1;
st_idx += 1;
}
return res;
}
};
题目链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
class Solution {
public:
void quick_sort(vector<int> &nums, int l, int r)
{
if(l >= r) return;
int x = nums[(l + r) >> 1], i = l - 1, j = r + 1;
while(i < j)
{
do i++; while(nums[i] > x);
do j--; while(nums[j] < x);
if(i < j) swap(nums[i], nums[j]);
}
quick_sort(nums, l, j);
quick_sort(nums, j + 1, r);
}
int findKthLargest(vector<int>& nums, int k) {
quick_sort(nums, 0, nums.size() - 1);
return nums[k - 1];
}
};
借助STL
class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
priority_queue<int, vector<int>, greater<int>> pq;
for (auto& n : nums)
{
if (pq.size() >= k && pq.top() >= n) continue;
pq.push(n);
if (pq.size() > k)
{
pq.pop();
}
}
return pq.top();
}
};
自己实现down
class Solution {
public:
void down(vector<int>& a, int u, int n)
{
int t = u;
if(u * 2 <= n && a[u * 2] > a[t]) t = u * 2;
if(u * 2 + 1 <= n && a[u * 2 + 1] > a[t]) t = u * 2 + 1;
if(u != t) swap(a[u], a[t]), down(a, t, n);
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
nums.push_back(nums[0]);
for(int i = n/2; i; i--) down(nums, i, n);
int m = n;
int res = 0;
while(m-- && k--)
{
cout << nums[1] << " ";
res = nums[1];
nums[1] = nums[n];
n--;
down(nums, 1, n);
}
cout << endl;
return res;
}
};
标签:fas ast 快速 算法 using 条件 == 荷兰国旗问题 空间
原文地址:https://www.cnblogs.com/Trevo/p/12987496.html