c++版 leetcode 215

一、冒泡排序

时间复杂度:O(n²)1520ms

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int length=nums.size();
        for (int i = 0; i < length; i++) {
            for (int j = i + 1; j < length; j++) {
                if (nums[i] > nums[j]) {
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
        }
        //倒数第k个元素
        return nums[length-k];
    }
};

二、最大堆排序

Time:O(n)16ms
建堆的时间:O(n),排序堆的时间:O(n)

class Solution {
public:
	//排序堆
	void heap_Sort(vector<int>& sort, int n, int i) {
		for (int j = n-1; j >=0; --j) {
			swap(sort[j], sort[i]);
			//顺序乱了,再次堆化
			heapify(sort, j, 0);
		}
	}

	//堆化			对象容器	  容量	  首元素
	void heapify(vector<int>& ify, int n, int i) {
		if (n <= i) {
			return;
		}
		int c1 = i * 2 + 1;
		int c2 = i * 2 + 2;
		int max = i;
		if (c1<n && ify[c1] > ify[max]) {
			max = c1;
		}
		if (c2<n && ify[c2] > ify[max]) {
			max = c2;
		}
		if (max != i) {
			swap(ify[i],ify[max]);
			heapify(ify, n, max);
		}
	}

	//创建堆 
	void build_heap(vector<int>& bui, int n) {
		//找到末节点的父节点
		int i = n - 1;
		int parent = (i - 1) / 2;
		//堆化,使得该父节点一下的节点都符合规范,并依次堆化该父节点的上一节点
		for (int i = parent; parent >= 0; --parent) {
			heapify(bui, n, parent);
		}
	}

	int findKthLargest(vector<int>& nums, int k) {
		int n = nums.size();
		build_heap(nums, n);
		heap_Sort(nums, n, 0);
		return nums[n - k];
	}
};

二点五、最大堆优化

Time:O(n log n)8ms
建堆:O(n),根据k删除堆:O(klog n)

class Solution {
public:
	//排序堆{对代码不起作用但能使运行时间减少4ms}{迷惑}
	void heap_Sort(vector<int>& sort, int n, int i) {
		for (int j = n-1; j >=0; --j) {
			swap(sort[j], sort[i]);
			//顺序乱了,再堆化一次
			heapify(sort, j, 0);
		}
	}

	//堆化			对象容器	  容量	  要开始堆化的元素
	void heapify(vector<int>& ify, int n,     int i) {
		if (n <= i) {
			return;
		}
		int c1 = i * 2 + 1;
		int c2 = i * 2 + 2;
		int max = i;
		if (c1<n && ify[c1] > ify[max]) {
			max = c1;
		}
		if (c2<n && ify[c2] > ify[max]) {
			max = c2;
		}
		if (max != i) {
			swap(ify[i],ify[max]);
			heapify(ify, n, max);
		}
	}

	//创建大根堆 
	void build_heap(vector<int>& bui, int n) {
		//找到末节点的父节点
		int last_Node = n - 1;
		//parent=n/2
		int parent = (last_Node - 1)/2;//log n
		//堆化,使得该父节点一下的节点都符合规范,并依次堆化该父节点的上一节点
		for (int i = parent; i >= 0; --i) {
			heapify(bui, n, i);
		}
	}

	int findKthLargest(vector<int>& nums, int k) {
		int n = nums.size();//9
		build_heap(nums, n);
		if (k == 1) {
			return nums[0];
		}
		else {
		//利用k动态维护要弹出顶端元素的个数
			for (int j = 1; j < k; j++) {
				swap(nums[0], nums[n - j]);
				//每弹一次都堆化(符合规范)
				heapify(nums, n - j,0);
			}
			return nums[0];
		}
	}
};

三、最小堆

Time:O(nlogn)100ms
建堆:O(k);维护堆:O(nlogn)

class Solution {
public:
	//堆排序(还是没用,提升速度而已)
	void heap_Sort(vector<int> &sor, int n) {
		for (int i = n - 1; i >=0; i--) {
			swap(sor[i], sor[0]);
			heapify(sor, i, 0);
		}
		for (int z = 0; z < n; z++) {
			cout << sor[z] << " ";
		}
		cout << endl;
		cout << "---------------------" << endl;
	}

	//堆化				数组    容量    堆化起点
	void heapify(vector<int>&ify, int n, int i) {
		if (i >= n) {
			return;
		}
		int c1 = i * 2 + 1;
		int c2 = c1 + 1;
		int min = i;
		if (c1 < n && ify[c1] < ify[min]) {
			min = c1;
		}
		if (c2 < n && ify[c2] < ify[min]) {
			min = c2;
		}
		if (min != i) {
			swap(ify[i], ify[min]);
			heapify(ify, n, min);
		}
	}

	//	创建最小堆						数组   总容量   维护个数 
	vector<int> build_MinHeap(vector<int>&bui,   int n,  int k) {
		//维护一个容量为k的最小堆
		vector<int> kmin;
		for (int i = 0; i < k; i++) {
			//将原数组的值赋给最小堆
			kmin.push_back(bui[i]);
		}
		//初始堆化
		int partent = (k / 2) - 1;
		for (int i = partent; i >= 0; --i) {
			heapify(kmin, k, i);
		}
		//将数组的下一个值加入堆
		for (int j = k; j < n; j++) {
			kmin.push_back(bui[j]);
			//堆化
			int partent1 = (k+1 / 2) - 1;
			for (int i = partent1; i >= 0; --i) {
				heapify(kmin, k+1, i);
			}
			//将最小值换到末尾
			swap(kmin[k], kmin[0]);
			//堆化
			heapify(kmin, k, 0);
			//删除末尾
			kmin.pop_back();
		}
		return kmin;
	}

	int findKthLargest(vector<int> &nums, int k) {
		int n = nums.size();//6
		auto kmin = build_MinHeap(nums, n, k);
		return kmin[0];
	}
};

四、快速排序

Time:O(nlogn)180ms

class Solution {
public:
	//查找正在排序的元素的下标
	int find_Pos(vector<int>&fin, int l, int h) {
		int val = fin[h];
		while (l < h) {
			while (l<h && fin[l]>=val) {
				l++;
			}
			fin[h] = fin[l];
			while (l < h && fin[h] <= val) {
				h--;
			}
			fin[l] = fin[h];
		}
		fin[l] = val;
		return l;
	}

	//快速排序(大到小)		数组		起始下标	截止下标	
	void quike_Sort(vector<int>&qs,		int l,		 int h) {
		if (l < h) {
			int pos = find_Pos(qs, l, h);
			quike_Sort(qs, l, pos - 1);
			quike_Sort(qs, pos + 1, h);
		}
	}

	int findKthLargest(vector<int>&nums, int k) {
		int n=nums.size();
		quike_Sort(nums, 0, n-1);
		return nums[k-1];
	}
};

四点五、快速排序

Time:O(logn)8ms
随机选取数进行排序:O(logn)

class Solution {
public:
	//查找正在排序的元素的下标
	int find_Pos(vector<int>&fin, int l, int h) {
		//随机选择一个下标与末尾交换
		int ran = l+rand()% (h-l+1);///区间:l~h
		swap(fin[ran], fin[h]);
		int val = fin[h];
		while (l < h) {
			while (l < h && fin[l] >= val) {
				l++;
			}
			fin[h] = fin[l];
			while (l < h && fin[h] <= val) {
				h--;
			}
			fin[l] = fin[h];
		}
		fin[l] = val;
		return l;
	}

	//快速排序(大到小)		数组		起始下标	截止下标	所求下标	
	int quike_Sort(vector<int>&qs,		int l,		 int h,		int k) {
	//leetcord中必须把判断语句删了,不然返回值错误
		//if (l <= h) {
			int pos = find_Pos(qs, l, h);
			if (pos == k - 1) {
				return qs[pos];
			}
			if (pos > k - 1) {
				quike_Sort(qs, l, pos - 1, k);//左排序
			}
			else {
				quike_Sort(qs, pos + 1, h, k);//右排序
			}
		//}
	}

	int findKthLargest(vector<int>&nums, int k) {	
		srand((unsigned int) time(NULL));
		int n=nums.size();
		return quike_Sort(nums, 0, n-1,k);
	}
};

快速选择

Time:O(n)8ms
一个随机for

class Solution {
public:
//                  容器            头节点  尾节点     索引
    int quickSelect(vector<int>& a, int l, int r, int index) {
//         下标             容器  头节点  尾节点
        int q = randomPartition(a, l, r);
            if (q == index) {
            return a[q];
        } else {
            // 下标是否小于索引               是:左递归             否:右递归
            return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
        }
    }
// 寻找下标                            容器     头节点  尾节点
    inline int randomPartition(vector<int>& a, int l, int r) {
        // 在给定区间内随机选择一个下标
        int i = rand() % (r - l + 1) + l;
        // 交换选择的元素和末元素
        swap(a[i], a[r]);
        //所选择的元素在数组中的位置
        return partition(a, l, r);
    }
//          划分                容器     头节点  尾节点
    inline int partition(vector<int>& a, int l, int r) {
        // x是尾节点值  i是头节点减一
        int x = a[r], i = l - 1;
        // 从头节点减一开始 枚举至尾节点
        for (int j = l; j < r; ++j) {
            // 若枚举的元素 小于尾节点值
            if (a[j] <= x) {
                // 交换 此元素前的数组中第一个不符合该循环的元素(大于尾节点值)和当前枚举的元素
                // 若此元素前的数组中没有第一个不符合该循环的元素,则不交换(交换自身)
                swap(a[++i], a[j]);
            }
        }
        // 交换前面都小于尾节点值得位置
        swap(a[i + 1], a[r]);
        // 返回该位置的下标
        return i + 1;
    }

    int findKthLargest(vector<int>& nums, int k) {
        srand(time(0));
        return quickSelect(nums, 0, nums.size() - 1, nums.size() - k);
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值