面试算法题
创始人
2024-01-19 20:06:06

文章目录

  • 数组中的第K个最大元素
    • 快排
  • k个一组反转链表
    • 解法一:栈
    • 解法二:模拟
  • 买卖股票最佳时机
    • 买卖股票最佳时机i
    • 买卖股票最佳时机ii
      • 贪心
  • 无重复长度子串
  • 最长递增子序列
  • 只出现一次的数字 III
  • lru缓存
  • 合并K个升序链表

数组中的第K个最大元素

快排

请添加图片描述

class Solution {
public:void quickPartition(vector& nums, int start, int end, int target) {// 随机取一个数作为基准int random = (end - start) + start;int base = nums[random];// 将该数放到待快排区间开头第一个元素swap(nums[start], nums[random]);int index = start;// 从待快排区间的第二个元素开始,依次与base比较,如果大于等于base则将该元素// 交换到index + 1位置,index++,使得最终index前面的元素都比base大。for (int i = start + 1; i <= end; ++i) {if (nums[i] >= base) {swap(nums[index + 1], nums[i]);index++;}}// base存放在区间开头,现在需要把它交换到index位置,这就是它在整个有序数组中的位置。swap(nums[index], nums[start]);// 如果index小于target,需要在右边区间继续快排查找,否则到在边区间查找,// 如果等于已经找到目标值不需要递归,这里这么做优化了传统快排的复杂度。if (index < target) {quickPartition(nums, index + 1, end, target);}else if (index > target) {quickPartition(nums, start, index - 1, target);}}int findKthLargest(vector& nums, int k) {// 方法1. 快速排序的分区思想,快排的思想是一次找出一个数的正确位置,// 并使得该数左边的元素都比它小,该数右边的元素都比它大,要找出第k// 大的元素,只需要在快排的时候采用降序排序,找到下标为k-1的元素即可。quickPartition(nums, 0, nums.size() - 1, k - 1);return nums[k - 1];}
};

k个一组反转链表

解法一:栈

class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {if (k <= 1)//首先判断k的合法性return head;stack myStack;//辅助栈,用于转换k个节点的转换int count = 0;//进栈的节点数ListNode *ptr = head;//进栈k个节点while (count < k && ptr != NULL){myStack.push(ptr);ptr = ptr->next;++count;}if (count < k){//如果不足k个,则无需转换return head;}//出栈并且顺序串接好//pHead是逆置结果的表头,pEnd是逆置结果的临时表尾ListNode *pHead = myStack.top(), *pEnd;myStack.pop();pEnd = pHead;while (count > 1){pEnd->next = myStack.top();pEnd = pEnd->next;myStack.pop();--count;}//递归调用,将ptr后面的链表进行逆置pEnd->next = reverseKGroup(ptr, k);return pHead;}
};

解法二:模拟

思路:可以把整段链表分为

  1. 已反转
  2. 即将反转但未反转
  3. 未反转
class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {if (!head) {return head;}int loop = 0;	//计数第几个节点,用于判断是否ListNode* p = head;		ListNode* pHead = p;ListNode* pLast = p;while (p) {++loop;if (loop % k == 0) {ListNode* temp = reverse(pHead, p);if (loop == k) {head = temp;	//第一次到达k时,此时返回的head就是最终的head} else {pLast->next = temp;		//非第一次到达k时,把刚反转的那一段链表的头节点接到上一次已反转的尾部}p = pHead;pHead = p->next;pLast = p;}p = p->next;}return head;}ListNode* reverse(ListNode* head, ListNode* last) {		//给定一个头节点一个尾节点,反转链表ListNode* realhead = last->next;	//把未到达的那个节点连接到尾部,便于后面正常遍历while (realhead != last) {ListNode* p = head->next;head->next = realhead;realhead = head;head = p;}return realhead;}
};

买卖股票最佳时机

买卖股票最佳时机i

  • dp:维护最大利润,维护最小买入值
class Solution {
public:int maxProfit(vector& prices) {int maxAns = 0;int minPrice = 99999;for (int i = 0; i < prices.size(); i++) {minPrice = min(minPrice, prices[i]); maxAns = max(maxAns,prices[i] - minPrice);}return maxAns;}
};

买卖股票最佳时机ii

贪心

  • 对于 「今天的股价 - 昨天的股价」,得到的结果有 3 种可能:① 正数,② 000,③负数。贪心算法的决策是: 只加正数 。
class Solution {
public:int maxProfit(vector& prices) {int maxP = 0;for (int i = 1; i < prices.size(); i++) {maxP += max(0, prices[i] - prices[i-1]);}return maxP;}
};

无重复长度子串

class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_map  map;		//int left = 0, size = s.length();int ans = 1, right = 1;map[s[left]] = 1;if (!size) {return 0;}while (right < size) {if (map.find(s[right]) != map.end()) { //如果遍历的这个字符在map里,把left位置的字符从map里删除,并right不动,left++ans = max(ans, right-left);map.erase(s[left]);++left;} else {		//当遍历的这个字符不存在map里,就往后走,并把该字符添加到map里map[s[right]] = 1;++right;}}ans = max(ans, right-left);return ans;}
};

最长递增子序列

维护dp数组里的最大值
维护已遍历原数组里最大值,每次与最大值比较,如果大于max,就让dp数组的该索引值为++max。否则还为max

class Solution {
public:int lengthOfLIS(vector& nums) {vector dp(nums.size(), 1);dp[0] = 1;int ans = 1;for (int i = 1; i < nums.size(); i++) {for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {dp[i] = max(dp[i], dp[j]+1);ans = max(ans, dp[i]);}}}return ans;}
};

只出现一次的数字 III

利用一个hashmap,出现一次的保留在map里,出现第二次就从map里删除

class Solution {
public:vector singleNumber(vector& nums) {unordered_map  map;vector ans;for (int i = 0; i < nums.size(); i++) {if (map.find(nums[i]) != map.end()) {map.erase(nums[i]);} else {map[nums[i]] = 1;}}for (auto& it : map) {ans.push_back(it.first);}return ans;}
};

lru缓存

struct linkList {		//创建双向链表int key, value;linkList* next;linkList* prev;
};
class LRUCache {
public:int size;int capacity;linkList* head;			//保留住头节点位置,头节点的下一个为最新的linkList* last;			//保留尾节点,尾节点的上一个为最旧的unordered_map  map;LRUCache(int capacity) {		//初始化size = 0;this->capacity = capacity;head = new linkList;last = new linkList;head->next = last;last->prev = head;}int get(int key) {if (map.find(key) == map.end()) {	//未找到return -1;} else {moveToFirstNode(map[key]);		//移到头节点后面return map[key]->value;}}void put(int key, int value) {			if (map.find(key) != map.end()) {		//如果在map里找到了该key,就从value保存的节点修改值就好,然后再移到首部map[key]->value = value;moveToFirstNode(map[key]);return;}if (size < capacity) {					//缓存够的话,直接放进首部map[key] = addNode(key, value);++size;} else {removeNode();map[key] = addNode(key, value);		//缓存不够,需要移除尾节点,再把新添加的节点放到首部}}linkList* addNode(int key, int value) {linkList* p = new linkList;		//设值p->value = value;p->key = key;head->next->prev = p;			//头插法p->next = head->next;p->prev = head;head->next = p;return p;}void removeNode() {				//移除最后一个节点linkList* pRemove = last->prev;			linkList* temp = last->prev->prev;temp->next = last;last->prev = temp;map.erase(pRemove->key);delete pRemove;}void moveToFirstNode(linkList* p) {			//把节点p从中间断开再放入首部linkList* temp = p->prev;			//断开,并把分隔开的上下两个节点连接好linkList* pNext = p->next;temp->next = pNext;pNext->prev = temp;head->next->prev = p;			//放到首部p->next = head->next;p->prev = head;head->next = p;}
};

合并K个升序链表

我们需要维护当前每个链表没有被合并的元素的最前面一个,k 个链表就最多有 k 个满足这样条件的元素,每次在这些元素里面选取 val 属性最小的元素合并到答案中。在选取最小元素的时候,我们可以用优先队列来优化这个过程。

class Solution {
public:struct comp {		//	重载运算符bool operator () (ListNode* a, ListNode* b) {return a->val > b->val;}};priority_queue, comp> q;ListNode* mergeKLists(vector& lists) {for (auto node: lists) {if (node) {q.push(node);}}ListNode* head = new ListNode();ListNode* tail = head;while (!q.empty()) {ListNode* node = q.top();q.pop();tail->next = node; tail = tail->next;if (node->next) {q.push(node->next);}}return head->next;}
};

上一篇:春五杂歌

下一篇:写生桃花歌

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
苁蓉的食用方法 鲜苁蓉的吃法有... 肉苁蓉号称“温而不热,补而不峻,暖而不燥,滑而不泄,故有从容之名。”历来也是传统药食同源的滋补佳品。...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
阳澄湖在哪里哪个省的 阳澄湖是... 点击题目下方苏州生活指南有用 有趣 有态度近期的阳澄湖度很高,3月24日,央视二套《第一时间》直播连...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...