程序员进阶之算法练习:LeetCode专场

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由落影发表

前言

LeetCode上的题目是大公司面试常见的算法题,今天的目标是拿下5道算法题: 题目1是基于链表的大数加法,既考察基本数据结构的了解,又考察在处理加法过程中的边界处理; 题目2是求数组出现频率前k大的数字,考察思维能力,代码很短; 题目3是给出从两个数组中选择数字,组成一个最大的数字,考察的是贪心的思想; 前三个都偏向于考察想法,实现的代码都比较简单; 题目4、5是数据结构实现题,也是大部分人比较头疼的题目,因为需要较多的数据结构和STL实现,并且还有时间和空间的限制。

正文

1、Add Two Numbers II

题目链接 题目大意

给俩个链表,节点由0~9的数字组成,分别表示两个数字; 求出两个数字的和,以链表的形式返回。

例如
Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)7243 + 564 =7807Output: 7 -> 8 -> 0 -> 7

题目解析: 题目的意思很明显,就是把两个数字加起来,需要考虑进位的情况。 因为是单向的链表,遍历后很难回溯,所以先把数字存到vec中。 并且为了处理方便,vec的最低位存在vec的起始部分。 于是从0开始遍历两个vec即可,注意考虑最后进位的情况。

复杂度解析: 时间复杂度是O(N) 空间复杂度是O(N)

struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode *ret = NULL;vector<int> vec1, vec2;sum(l1, vec1);sum(l2, vec2);int n = vec1.size(), m = vec2.size(), flag = 0;for (int i = 0; i < n || i < m; ++i) {int x = 0, y = 0;if (i < n) {x = vec1[i];}if (i < m) {y = vec2[i];}int s = x + y + flag;if (s > 9) {s -= 10;flag = 1;}else {flag = 0;}ListNode *tmp = new ListNode(s);tmp->next = ret;ret = tmp;}if (flag) {ListNode *tmp = new ListNode(1);tmp->next = ret;ret = tmp;}return ret;}void sum(ListNode* list, vector<int> &vec) {if (list->next) {sum(list->next, vec);}vec.push_back(list->val);}
};

2.Top K Frequent Elements

题目链接 题目大意

给出一个数组和一个数字k,返回按数字出现频率的前k个的数字; 1 <= k <= n, n是数组大小;

 example,Given [1,1,1,2,2,3] and k = 2, return [1,2].

题目解析:

题目分为两个步骤: 1、统计每个数字的出现次数; 2、从中选择k个次数最多的数字;

一个简单的做法: 用哈希表统计每个数字的出现次数; 把每个数字的出现次数和数字组成一个pair,放入优先队列;

这样从优先队列中取出k个即可。

复杂度解析: 时间复杂度是O(NlogN),主要在最后的优先队列。

其他解法: 有一个O(NlogK)的优化; 首先把队列变成最小有限队列, 每次pair放入优先对时,如果当前的size大于k,那么弹出top; 这样每次的操作从O(logN)变成O(logK)。

class Solution {
public:vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int, int> numsHash;for (int i = 0; i < nums.size(); ++i) {++numsHash[nums[i]];}priority_queue<pair<int, int>> q;for (int i = 0; i < nums.size(); ++i) {if(numsHash[nums[i]]) {q.push(make_pair(numsHash[nums[i]], nums[i]));numsHash[nums[i]] = 0;}}vector<int> ret;for (int i = 0; i < k; ++i) {ret.push_back(q.top().second);q.pop();}return ret;}
}leetcode;

3、create-maximum-number

题目链接 题目大意: 给出两个数组,数组只包括0~9十个数字,长度分别为n、m; 从两个数组中选出k个数,组成一个长度为k的数字,要求: 1、从数组n、m选择出来的数字相对位置不变; 2、最后的数字最大; 输出最后的数字。

 Example 1:nums1 = [3, 4, 6, 5]nums2 = [9, 1, 2, 5, 8, 3]k = 5return [9, 8, 6, 5, 3]Example 2:nums1 = [6, 7]nums2 = [6, 0, 4]k = 5return [6, 7, 6, 0, 4]

题目解析:

要求最后数字最大,那么尽可能把数字大的排在前面; 在都合法的前提下,99* 肯定比 98*要大; 那么可以按照这样的贪心策略: 先枚举t,t表示从数组nums1中选出t个数字,那么数组nums2中应该选出k-t个数字; 两个数组的所有数字组成最大的数字,因为两个数组间的数字是可以任意顺序,那么只需每次选择较大的放在前面即可。

问题简化成,O(N)每次从数组中选出t个最大的数字; 这个可以用贪心解决: 假设数组当前枚举到第i个,且nums[i]=x; 从左到右遍历已经选择的数,当遇到一个数字t,t<x时,判断插入x后,后续是否存在合法解;如果存在则替换,否则直到最后,插入尾部;

class Solution {
public:vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {int n = (int)nums1.size(), m = (int)nums2.size();vector<int> ret(k, 0);for (int i = max(0, k - m); i <= k && i <= n; ++i) {vector<int> tmp1 = maxArray(nums1, i);vector<int> tmp2 = maxArray(nums2, k - i);vector<int> tmp = merge(tmp1, tmp2, k);if (greater(tmp, 0, ret, 0)) {ret = tmp;}}return ret;}vector<int> maxArray(vector<int> &nums, int k) {int n = (int)nums.size();vector<int> ret(k, 0);for (int i = 0, j = 0; i < n; ++i) {while (n - i + j > k && j > 0 && ret[j - 1] < nums[i]) {--j;}if (j < k) {ret[j++] = nums[i];}}return ret;}vector<int> merge(vector<int>& nums1, vector<int>& nums2, int k) {vector<int> ret(k, 0);for (int i = 0, j = 0, r = 0; r < k; ++r) {ret[r] = greater(nums1, i, nums2, j) ? nums1[i++] : nums2[j++];}return ret;}bool greater(vector<int> &nums1, int i, vector<int> &nums2, int j) {while (i < nums1.size() && j < nums2.size() && nums1[i] == nums2[j]) {++i;++j;}return j == nums2.size() || (i < nums1.size() && nums1[i] > nums2[j]);}
};

4、 Insert Delete GetRandom O(1) - Duplicates allowed

题目链接 题目大意: 实现一个数据结构,包括以下三个方法: 1、insert(val): 插入一个数字; 2、remove(val): 移除一个数字; 3、getRandom: O(1)随机返回一个数字;

 Example插入数字1;collection.insert(1);插入数字1:collection.insert(1);插入数字2collection.insert(2);随机返回数字,要求 2/3可能返回1, 1/3可能返回2;collection.getRandom();

题目解析:

插入和移除数字不麻烦,考虑如何在O(1)时间返回一个数字。 容易知道,放在数组里面可以,然后随机返回一个位置可以实现。 增加可以在数组最末端增加; 删除数组中间某个数字时,可以把最末端的数字放到删除的位置上;

现在的问题是,如何快速找到数组中该删除的某个位置; 考虑用hash来实现。 数组就是vector<pair<int, int> >; first存val,second存出现次数; 再用一个哈希map,unordered_map<int, vector> 里面存对应数字出现的位置;

class RandomizedCollection {
public:/** Initialize your data structure here. */RandomizedCollection() {}/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */bool insert(int val) {bool ret = hashMap.find(val) == hashMap.end();hashMap[val].push_back(randVec.size());randVec.push_back(make_pair(val, hashMap[val].size() - 1));return ret;}/** Removes a value from the collection. Returns true if the collection contained the specified element. */bool remove(int val) {bool ret = hashMap.find(val) != hashMap.end();if (ret) {auto last = randVec.back();hashMap[last.first][last.second] = hashMap[val].back();randVec[hashMap[val].back()] = last;hashMap[val].pop_back();if (hashMap[val].empty()) {hashMap.erase(val);}randVec.pop_back();}return ret;}/** Get a random element from the collection. */int getRandom() {return randVec[rand() % randVec.size()].first;}private:unordered_map<int, vector<int>> hashMap;vector<pair<int, int>> randVec;
}leetcode;

5、 All O`one Data Structure

题目链接 题目大意

实现一个数据结构,要求: 1、Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string. 2、Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string. 3、GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "". 4、GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "".

要求所有的数据结构的时间复杂度是O(1);

题目解析:

在不考虑复杂度的前提下,朴素做法是遍历,O(N); 简单的优化,用map来维护优先队列,操作1、2先获取key值,更新完重新插入;操作3、4直接拿队列top;每个操作的复杂度是O(LogN);

题目要求是O(1),那么必然不能使用树类型的结构,应该利用题目特性,配合hash以及贪心来实现。

假设有一个key-hash表,来存key的对应值。 操作1、先看keyHash里面是否有key,有则+1,无则插入; 操作2、先看keyHash里面是否有key,有则-1,无则Nothing;

为了维护最值,引入链表list,里面所有的元素是从小到大;每个元素是一个桶,桶里放着值相同的key; 操作3、直接获取list头元素的值; 操作4、直接获取list尾元素的值;

同时,操作1、2在操作的过程中,需要把当前key值从list对应的桶里移除,放到上一个或者下一个桶里,或者丢弃。 为了实现O(1)获取key所在位置,可以用iter-hash来维护key所对应元素的迭代器。

struct Bucket {int value;unordered_set<string> keys;
};class AllOne {
public:list<Bucket> buckets;unordered_map<string, list<Bucket>::iterator> bucketOfKey;/** Initialize your data structure here. */AllOne() {}/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */void inc(string key) {if (bucketOfKey.find(key) == bucketOfKey.end()) {bucketOfKey[key] = buckets.insert(buckets.begin(), {0, {key}});}auto next = bucketOfKey[key], bucket = next++;if (next == buckets.end() || next->value > bucket->value + 1) {next = buckets.insert(next, {bucket->value+1, {}});}next->keys.insert(key);bucketOfKey[key] = next;bucket->keys.erase(key);if (bucket->keys.empty()) {buckets.erase(bucket);}}/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */void dec(string key) {if (bucketOfKey.find(key) == bucketOfKey.end()) {return ;}auto pre = bucketOfKey[key], bucket = pre;if (pre != buckets.begin()) {--pre;}bucketOfKey.erase(key);if (bucket->value > 1) {if (bucket == buckets.begin() || pre->value < bucket->value - 1) {pre = buckets.insert(bucket, {bucket->value - 1, {}});}pre->keys.insert(key);bucketOfKey[key] = pre;}bucket->keys.erase(key);if (bucket->keys.empty()) {buckets.erase(bucket);}}/** Returns one of the keys with maximal value. */string getMaxKey() {return buckets.empty() ? "" : *(buckets.rbegin()->keys.begin());}/** Returns one of the keys with Minimal value. */string getMinKey() {return buckets.empty() ? "" : *(buckets.begin()->keys.begin());}
}leetcode;

总结

这5个题目如果都能独立完成,那么水平已经可以足以应付国内各大企业的算法面。 算法重在勤思多练,埋怨公司出算法题是没用的,多花时间准备才是正道。

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

转载于:https://www.cnblogs.com/qcloud1001/p/10021759.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450547.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vim 安装vim-prettier

1、在.vimrc中添加 配置没有安装成功的话 git clone https://github.com/prettier/vim-prettier Plug prettier/vim-prettier, { do: yarn install, for: [javascript, typescript, css, less, scss, json, graphql, markdown, vue, yaml, html, php] } let g:prettier#aut…

详解Mysql中的JSON系列操作函数

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、方法罗列&#xff1a; 分类 函数 描述创建jsonjson_array 创建json数组json_object 创建json对象 json_quote 将json转成json字符串…

WEB/H5性能优化总结

我们今天来说说前端图形渲染优化&#xff0c;因为我接下来的时间可能要开始研究webgl方面的东西&#xff0c;所以就在这里把之前做过的H5做一个总结&#xff0c;现同步发布于GERRY_BLOG&#xff0c;TiMiGerry-知乎&#xff0c;转载请保留链接。静态资源-图片 一 、图片格式JPEG…

C语言数组参数与指针参数

我们都知道参数分为形参和实参。形参是指声明或定义函数时的参数&#xff0c;而实参是在调用函数时主调函数传递过来的实际值。 一、一维数组参数 1、能否向函数传递一个数组&#xff1f;看例子&#xff1a;void fun(char a[10]){char c a[3];}intmain(){char b[10] “abcd…

maven文件结构

pom.xml 用于maven的配置文件 /src 源代码目录 /src/main 工程源代码目录 /src/main/java 工程java源代码目录 /src/main/resource 工程的资源目录 /src/test 单元测试目录 /src/test/java /target 输出目录&#xff0c;所有的输出都存放在这个目录下 /target/classes 编译之…

php如何使用高阶函数

1、首先学会数组转集合的方式 &#xff08;1&#xff09;使用collect函数 $arr [1, 2, 3, 4, 5]; $collect collect($arr); &#xff08;2&#xff09;使用array_map函数 $arr [1, 2, 3, 4, 5]; $collect array_map(function($item){ return $item *…

Git 使用,命令说明

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. D:\ChengXu\git\Git中双击Git Bash启动git窗口。 2. 这条不能放到博客&#xff0c;是我的账号密码。 3. 添加&#xff1a; git add …

2017ACM/ICPC亚洲区沈阳站 C Hdu-6219 Empty Convex Polygons 计算几何 最大空凸包

题面 题意:给你一堆点,求一个最大面积的空凸包,里面没有点. 题解:红书板子,照抄完事,因为题目给的都是整点,所以最后答案一定是.5或者.0结尾,不用对答案多做处理 1 #include<bits/stdc.h>2 #define N 553 using namespace std;4 struct rec5 {6 double x,y;7 };8 rec…

python读xml文件

# -*- coding:utf-8 -*- import jsonimport requestsimport oscurpathos.path.dirname(os.path.realpath(__file__))xmlpathos.path.join(curpath,read1.xml)with open(xmlpath,encoding"utf-8") as fp: bodyfp.read() print(body)转载于:https://www.cnblogs.…

C语言数组应用

一、数组的内存布局 先看下面的例子&#xff1a;int a[5];所有人都明白这里定义了一个数组&#xff0c;其包含了5 个int 型的数据。我们可以用a[0],a[1]等来访问数组里面的每一个元素&#xff0c;那么这些元素的名字就是a[0],a[1]…吗&#xff1f;看下面的示意图&#xff1a; 如…

Installation failed, deleting ./composer.json.安装phpunit报错解决方案

是因为你没有装全局的phpunit&#xff0c;安装命令 composer global require phpunit/phpunit 之后你输入 composer require --dev phpunit/phpunit 就发现你安装成功了

MyBatis在Oracle中插入数据并返回主键的问题解决

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 前言&#xff1a;我早期用过这个方法&#xff0c;但是返回的依旧是影响行数&#xff0c;不是主键。 只是这种写法可以达到我要的效果&a…

在 Intellij IDEA 里使用 OpenJFX (JavaFX)

2019独角兽企业重金招聘Python工程师标准>>> JDK 11 把 JavaFX 剥离了出来&#xff0c;形成了单独且开源的 OpenJFX 模块。 本文的目的是通过简单的例子解释这一变化对使用 JavaFX 所造成的影响&#xff0c;并找到一种在 IDEA 2018.2 上使用它的办法。 首先&#xf…

使用phpunit新建项目

1、mkdir test-project 新建一个test-project 2、cd test-project 跑到文件夹中 3、实例化git git init 4、新建phpunit项目 composer require --dev phpunit/phpunit 5、使用gi实例化.gitignore gi composer>.gitignore (如果没有安装gi&#xff0c;请使用命令ec…

如何解决eclipse里面tomcat 8080端口被占用

很多时候运行tomcat 的时候总是会提示tomcat 的端口被占用 但是任务管理器里面还找不到是哪个端口被占用了 因此很多人就重新配置tomcat 或者去修改tomcat的端口号 &#xff0c;其实这么做太麻烦了 &#xff0c;小弟在这里告诉你一个非常简单的方法。 1.在开始菜单中选择运行 …

Selenium UI 举例 getCssValue

selenium jar包中&#xff0c;在WebElement的接口中&#xff0c; String getCssValue(String var1);可以通过标签&#xff0c;获取对应的css值。具体要怎么用呢&#xff0c;如下&#xff1a; WebElement baidu driver.findElement(By.id("su"));su.getCssValue(&quo…

java集合框架中contains(),containsKey()和containsValue()的用法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 java集合框架中contains(),containsKey()和containsValue()的用法&#xff1a; List集合的contains()方法用于判断集合中包不包含某个元…

敏捷视频

规模化极限编程的关键抓手&#xff1a;验收条件https://mp.weixin.qq.com/s/aHlSxpMx7DTQXaoEgcAQ3g 5分钟让你子解持续集成https://www.bilibili.com/video/BV1SK411W77W/?spm_id_fromtrigger_reload 5分钟让你学会返工率降低1倍的神技--开卡、验卡https://www.bilibili.com/…

提问的智慧

提问的智慧转载于:https://www.cnblogs.com/whigym/p/10028642.html

C语言指针和数组概述

几乎每次讲课讲到指针和数组时&#xff0c;我总会反复不停的问学生&#xff1a;到底什么是指针&#xff1f;什么是数组&#xff1f;他们之间到底是什么样的关系。从几乎没人能回答明白到几乎都能回答明白&#xff0c;需要经历一段“惨绝人寰”的痛。指针是C/C的精华&#xff0c…