链接:https://leetcode.com/tag/sort/

【56】Merge Intervals (2019年1月26日,谷歌tag复习)

合并区间

Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

题解:先按照interval的begin从小到大sort一下,然后顺序遍历,能合并的就合并,不能合并的就加入一个新的interval。

 /**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
//time complexity: O(nlogn)
class Solution {
public:
vector<Interval> merge(vector<Interval>& intervals) {
sort(intervals.begin(), intervals.end(), cmp);
vector<Interval> ret;
for (auto inter : intervals) {
if (ret.empty()) {
ret.push_back(inter);
continue;
}
if (inter.start > ret.back().end) {
ret.push_back(inter);
} else {
ret.back().end = max(inter.end, ret.back().end);
}
}
return ret;
}
static bool cmp (const Interval& inter1, const Interval& inter2) {
return inter1.start < inter2.start;
}
};

【57】Insert Interval (2019年1月26日,谷歌tag复习)

Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).

You may assume that the intervals were initially sorted according to their start times

Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]

Output: [[1,2],[3,10],[12,16]]

Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].

题解:先按照插入排序把需要插入的interval放在原来intervals中合适的位置,然后合并区间。

 /**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
const int n = intervals.size();
int i = ;
for (; i < n; ++i) {
if (intervals[i].start >newInterval.start) {
auto iter = intervals.begin() + i;
intervals.insert(iter, newInterval);
break;
}
}
if (i == n) {
intervals.push_back(newInterval);
}
vector<Interval> ret;
for (auto interval : intervals) {
if (ret.empty() || ret.back().end < interval.start) {
ret.push_back(interval);
} else {
ret.back().end = max(interval.end, ret.back().end);
}
}
return ret;
}
};

【75】Sort Colors (2018年12月11日,wiggle sort专题复习,荷兰国旗问题)

给了一个数组,包含重复的 0,1,2 三种数字,实现一种操作,能用 one pass,O(1) 的space把这个数组变成0,1,2的顺序数组。

题解:用三根指针,left,right,mid。最后的时候 left 指向 1 的第一个元素,right 指向 1 的最后一个元素。

2019年1月20日补充,left一开始在最左边,right一开始在最右边,我们有一个能够往前移动的指针叫做point或者mid,我们想用mid指针遍历过整段的1,所以如果当前的mid指针指向的是0的话,我们想把这个0放到最前面去,所以把这个0和前面的left做交换,left++,mid++。如果当前的mid指针指向的是 2 的话,我们把它和后面的right做交换,--right,但是这里不能++mid,因为有可能原来的 right位置就是 2,交换完了之后 mid 指向的还是 2.

 //荷兰国旗问题
class Solution {
public:
void sortColors(vector<int>& nums) {
const int n = nums.size();
int left = , mid = , right = n-;
while (mid <= right) {
if (nums[mid] == ) {
swap(nums[left++], nums[mid++]);
} else if (nums[mid] == ) {
swap(nums[right--], nums[mid]);
} else {
mid++;
}
}
return;
}
};

【147】Insertion Sort List

【148】Sort List

【164】Maximum Gap

【179】Largest Number (2019年2月23日,M)

给了一个整数的数组,要求返回一个字符串,这个字符串由整数数组的元素拼接而成。每个元素只能用一次。求这个字符串转换成数字的最大值。

Input: [3,30,34,5,9]
Output: "9534330"

题解:我们想象一下比较两个数,3,和 30,这两个数应该谁在前谁在后,如果3在前面,30在后面,组成的数字是330,如果30在前面,3在后面,组成的数字是303。我们断定330肯定大于303。所以我们算法如下,把整数数组排列成字符串,并且给新的字符串数组排序。排序的规则我们自己定义,s1 + s2 > s2 + s1 返回true。

 class Solution {
public:
string largestNumber(vector<int>& nums) {
const int n = nums.size();
vector<string> strs(n);
for (int i = ; i < n; ++i) {
strs[i] = to_string(nums[i]);
}
sort(strs.begin(), strs.end(), cmp);
string res;
for (auto& s : strs) {
res += s;
}
while (res.size() > && res[] == '') {
res = res.substr();
}
return res;
}
static bool cmp(const string& s1, const string& s2) {
string t1 = s1 + s2, t2 = s2 + s1;
return t1 > t2;
}
};

【242】Valid Anagram

【252】Meeting Rooms (2018年11月22日,为了冲题量)

题意就是给了一个数组,数组里面的每个元素代表一个会议的开始时间和结束时间。问能不能用一个会议室安排下所有的会议。

题解:这题好像以前就做过类似的线段题,先给数组排序,用结束时间从小到大排序,如果结束时间相同,就按照开始时间从小到大排序。然后遍历数组,看前一个元素的结束时间是否小于等于当前元素的开始时间。 都满足条件返回 true,有一个不满足条件的返回false。

 /**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
bool canAttendMeetings(vector<Interval>& intervals) {
if (intervals.empty()) {return true;}
sort(intervals.begin(), intervals.end(), cmp);
for (auto i = ; i < intervals.size()-; ++i) {
if (intervals[i].end > intervals[i+].start) {
return false;
}
}
return true;
}
static bool cmp(const Interval& a, const Interval& b) {
if (a.end != b.end) {
return a.end < b.end;
}
return a.start < b.start;
}
};

【253】Meeting Rooms II (2018年11月22日,为了冲题量)

题意是252的升级版,给了一个数组,数组里面的每个元素代表一个会议的开始时间和结束时间,问想安排下所有的会议,至少需要多少个会议室。

题解:还是先排序。这次可能按照结束时间从大到小排序,结束时间相同的时候就按照开始时间从大到小排序,或者从小到大排序然后从后往前遍历都可以。用一个map记录key是会议室编号,value是这个会议室的下一个会议的开始时间。如果当前会议的结束时间小于等于下一个会议的开始时间就能放在这个会议室里面,不然需要重新开一个会议室。有一种case需要注意,如果我按照会议结束时间从小到大排序然后顺序安排,有可能有一个会议室的时间轴两个会议之间会有一段很大的gap,这个gap可能重新安排就能减少会议室的总体数量。按照结束时间从大到小排序能保证能一个会议室中间的gap不会很大。

 /**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
int minMeetingRooms(vector<Interval>& intervals) {
if (intervals.empty()) {return ;}
const int n = intervals.size();
sort(intervals.begin(), intervals.end(), cmp);
int ret = ;
map<int, int> mp; //roomNumber -> starttime
mp[ret] = intervals[].start;
for (int i = ; i < n; ++i) {
bool find = false;
for (auto& e : mp) {
if (e.second >= intervals[i].end) {
find = true;
e.second = intervals[i].start;
break;
}
}
if (!find) {
mp[++ret] = intervals[i].start;
}
}
return ret;
}
static bool cmp(const Interval& a, const Interval& b) {
if (a.end != b.end) {
return a.end > b.end;
}
return a.start > b.start;
}
};

这题还有个 greedy 和 heap 的标签,思想就是 greedy,heap怎么解不懂啊。

【274】H-Index

【280】Wiggle Sort (2018年12月11日,wiggle sort专题)

Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3]....

Example:
Input: nums = [3,5,2,1,6,4]
Output: One possible answer is [3,5,1,6,2,4]

题解:依次比较相邻的两个数,不符合条件的就做交换。

 class Solution {
public:
void wiggleSort(vector<int>& nums) {
const int n = nums.size();
for (int i = ; i < n; ++i) {
if (i & 0x1 && nums[i] < nums[i-]) {
swap(nums[i], nums[i-]);
} else if (i % == && nums[i] > nums[i-]) {
swap(nums[i], nums[i-]);
}
}
return;
}
};

2019年2月18日补充,时间复杂度是O(N)

【296】Best Meeting Point (2018年11月22日,开始做 hard 题)

给了一个二维的 0/1 矩阵grid, grid[i][j] = 1 代表 1 位置上有个人,现在矩阵上至少有两个人,这几个人想挑一个点 (x, y) 相会,问矩阵上的哪个点到这几个人的曼哈顿距离和最近,返回最近的距离之和。

曼哈顿距离的公式是 distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.

题解:我一开始就暴力了,时间复杂度是 O(n*m*k),然后居然卡着时间过了orz,只 beats 了 1.15%,尴尬。下面附上尴尬的强行解。

 class Solution {
public:
int minTotalDistance(vector<vector<int>>& grid) {
const int n = grid.size();
if (n == ) {return ;}
const int m = grid[].size();
if (m == ) {return ;}
vector<vector<int>> people;
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
if (grid[i][j]) {
people.push_back(vector<int>{i, j});
}
}
}
int ret = INT_MAX;
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
int summ = ;
for (int k = ; k < people.size(); ++k) {
summ += abs(i - people[k][]) + abs(j - people[k][]);
if (summ > ret) {break;}
}
ret = min(summ, ret);
}
}
return ret;
}
};

brute force

我们下面来看一下优秀的解法们:我们可以先分析一下一维数组的情况,我们假设这个数组是 [1,0,0,1,0,0,0,1],会面的位置选在第二个 1 的位置距离和最小。所以这个结论就是一维数组是选在前缀和的中位数上,median,如果是偶数个 1,比如 [1,1,0,1,1], 这个位置选在下标 1, 2, 3上都可以。因为是求曼哈顿距离,所以完全可以行和列分离,分解成两个一维数组的情况。我们首先对矩阵的行和列进行累加,把一个矩阵拍成一维数组,然后结果就是两个一维数组的距离之和。时间复杂度是(m*n*log(nm))

 class Solution {
public:
int minTotalDistance(vector<vector<int>>& grid) {
const int n = grid.size();
if (n == ) {return ;}
const int m = grid[].size();
if (m == ) {return ;}
vector<int> rows(m, ), cols(n, );
for (int j = ; j < m; ++j) {
for (int i = ; i < n; ++i) {
if (grid[i][j]) {
rows[j] += ;
cols[i] += ;
}
}
}
int ret = cope(rows) + cope(cols);
return ret;
}
int cope(const vector<int>& nums) {
const int n = nums.size();
vector<int> summ = nums;
for (int i = ; i < n; ++i) {
summ[i] += summ[i-];
}
int median = (summ[n-] + ) / ;
auto iter = lower_bound(summ.begin(), summ.end(), median);
int index = distance(summ.begin(), iter);
int ret = ;
for (int i = ; i < nums.size(); ++i) {
ret += abs(index - i) * nums[i];
}
/*
print("nums", nums);
print("summ", summ);
printf("median = %d, index = %d, ret = %d \n", median, index, ret);
*/
return ret;
}
void print(const string name, const vector<int>& nums) {
printf("%s: ", name.c_str());
for (auto n : nums) {
printf("%d ", n);
}
printf("\n");
} };

还可以更加优化,见solution的最后一个解法,它能把时间复杂度搞成 O(mn)。唉我不想看了,

【324】Wiggle Sort II (2019年2月20日)

摆动排序。Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....

Example 1:
Input: nums = [1, 5, 1, 1, 6, 4]
Output: One possible answer is [1, 4, 1, 5, 1, 6].
Example 2:
Input: nums = [1, 3, 2, 2, 3, 1]
Output: One possible answer is [2, 3, 1, 3, 1, 2].

Can you do it in O(n) time and/or in-place with O(1) extra space?

题解:我们先把数组排序,然后找到中位数。然后我们用中位数把数组分成两半,如果是奇数长度,前半段长一点。然后我们用两根指针,同时从两段数组的末尾开始扫描。加入一个新的数组。这样就能保证前半段的数字一定小于后半段的数字。

这种解法时间复杂度是O(nlogn),空间复杂度是O(n)

 class Solution {
public:
void wiggleSort(vector<int>& nums) {
int n = nums.size();
if (n == ) {return;}
sort(nums.begin(), nums.end());
int k = (n-)/;
int p1 = k, p2 = n-;
vector<int> ret(n);
int idx = ;
while (idx < n) {
ret[idx++] = nums[p1--];
if (idx >= n) {break;}
ret[idx++] = nums[p2--];
}
nums = ret;
}
};

【349】Intersection of Two Arrays (2018年11月6日,算法群相关题)

给了两个数组,返回他们交叠的元素,如果有重复元素的话,只返回一个就行了。

hash-table 里面有这题,我就不重复写了。hash-table:https://www.cnblogs.com/zhangwanying/p/9886262.html

【350】Intersection of Two Arrays II (2018年11月6日,算法群)

给了两个数组,返回他们所有交叠的元素,元素可以任意顺序返回,但是如果一个元素在A,B数组中都出现多次,需要返回公共的多次。

hash-table 里面有这题,我就不重复写了。hash-table:https://www.cnblogs.com/zhangwanying/p/9886262.html

【524】Longest Word in Dictionary through Deleting (2019年2月23日)

给了一个字符串s,和一个 wordlist,找出list里面是 s 的子序列并且最长的一个单词,如果有两个单词相同长度,并且都是s的子序列,那么返回 lexicographcal order 小的那个。

Input:
s = "abpcplea", d = ["ale","apple","monkey","plea"]
Output:
"apple"

题解:我们需要依次判断列表中的单词是不是 s 的子序列。需要写一个 match 函数,然后依次判断可以,或者把列表排序后再判断也可以。

 class Solution {
public:
string findLongestWord(string s, vector<string>& d) {
const int n = d.size();
//sort(d.begin(), d.end(), cmp);
string res = "";
for (auto& t : d) {
if (match(s, t)) {
if (t.size() > res.size()) {res = t;}
if (t.size() == res.size()) {res = min(t, res);}
}
}
return res;
}
static bool cmp(const string& s1, const string& s2) {
if (s1.size() == s2.size()) {
return s1 < s2;
}
return s1.size() > s2.size();
}
bool match(const string& s, const string& t) {
if (s.size() < t.size()) {return false;}
const int ssize = s.size(), tsize = t.size();
int idx = ;
for (int i = ; i < ssize; ++i) {
if (idx < tsize && s[i] == t[idx]) {
++idx;
}
// if (idx == tsize) {return true;}
}
return idx == tsize;
}
};

【527】Word Abbreviation

【710】Random Pick with Blacklist

【767】Reorganize String

【LeetCode】排序 sort(共20题)的更多相关文章

  1. Leetcode 简略题解 - 共567题

    Leetcode 简略题解 - 共567题     写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...

  2. 【LeetCode】图论 graph(共20题)

    [133]Clone Graph (2019年3月9日,复习) 给定一个图,返回它的深拷贝. 题解:dfs 或者 bfs 都可以 /* // Definition for a Node. class ...

  3. 待字闺中之快排单向链表;leetcode之Sort List

    题目来源.待字闺中.原创@陈利人 .欢迎大家继续关注微信公众账号"待字闺中" 分析:思路和数据的高速排序一样,都须要找到一个pivot元素.或者节点. 然后将数组或者单向链表划分为 ...

  4. C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)

    leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/  Total Accepted: 68702 Total ...

  5. 设计模式 - 模板方法模式(template method pattern) 排序(sort) 具体解释

    模板方法模式(template method pattern) 排序(sort) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考模板方法模式(tem ...

  6. 给乱序的链表排序 · Sort List, 链表重排reorder list LoLn...

    链表排序 · Sort List [抄题]: [思维问题]: [一句话思路]: [输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入): [画图]: quick ...

  7. Java中Map<Key, Value>存储结构根据值排序(sort by values)

    需求:Map<key, value>中可以根据key, value 进行排序,由于 key 都是唯一的,可以很方便的进行比较操作,但是每个key 对应的value不是唯一的,有可能出现多个 ...

  8. 分享一组Rpg Marker人物行走,游戏素材图片,共20张图片

    分享一组Rpg Marker人物行走,游戏素材图片,共20张图片 上面的下载地址链接是图片,无法直接复制哦!下载请直接点击: 游戏素材下载  或者复制以下链接:http://***/view/13.h ...

  9. Lucene 排序 Sort与SortField

    在sql语句中,有升序和降序排列.在Lucene中,同样也有. Sort里的属性 SortField里的属性 含义 Sort.INDEXORDER SortField.FIELD_DOC 按照索引的顺 ...

随机推荐

  1. ubuntu下安装apatch

    在Ubuntu上安装Apache,有两种方式:1 使用开发包的打包服务,例如使用apt-get命令:2 从源码构建Apache.本文章将详细描述这两种不同的安装方式. 方法一:使用开发包的打包服务—— ...

  2. ping: sendto: No route to host

    root@tuhooo:/home/ # ping www.baidu.comPING www.a.shifen.com (61.135.169.125): 56 data bytesping: se ...

  3. leetcode 239. 滑动窗口最大值(python)

    1. 题目描述 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 示 ...

  4. ifram刷新父窗口中内嵌页面

    如果C的iframe标签的id是"iframec",那么在B.aspx中你想刷新的代码处写 parent.document.getElementById('iframec').sr ...

  5. LeetCode All in One 题目讲解汇总(转...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 如果各位看官们,大神们发现了任何错误,或是代码无法通 ...

  6. Python学习之==>有依赖关系的接口开发

    一.接口需求 1.登录接口 (1)登录成功后将session信息存入redis数据库并设置失效时间为600秒 (2)构造返回结果的对象flask.make_response() (3)产生cookie ...

  7. 一文学会Rust?

    Rust是什么 Rust 是一个系统编程语言,它注重三个方面:安全,速度和并发性. 特征: 1.没有垃圾回收机制,没有运行时,效率超过c++,直逼c语言 2.内存安全,并发安全,没有空指针 3.极其丰 ...

  8. 转:【开源必备】常用git命令

    原文:https://zhuanlan.zhihu.com/p/25868120 [开源必备]常用git命令 [已重置]   如今在技术领域,码农们习惯了开源,也离不开免费开源的代码,轻松获取代码,不 ...

  9. python3+selenium常用语法汇总

    Selenium常用语法总结 一.Selenium常用定位语法 1.元素定位 (1)ID定位元素: find_element_by_id(‘’) (2)通过元素的类名称定位元素: find_eleme ...

  10. cocos2dx基础篇(13) 编辑框之二CCEditBox

    [3.x] (1)去掉"CC" (2)设置虚拟键盘的编辑类型 > EditBoxInputMode 变为强枚举 EditBox::EditBoxInputMode // SI ...