第一题:二进制间距

问题:

给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离。

如果没有两个连续的 1,返回 0 。

示例 1:

输入:22
输出:2
解释:
22 的二进制是 0b10110 。
在 22 的二进制表示中,有三个 1,组成两对连续的 1 。
第一对连续的 1 中,两个 1 之间的距离为 2 。
第二对连续的 1 中,两个 1 之间的距离为 1 。
答案取两个距离之中最大的,也就是 2 。

示例 2:

输入:5
输出:2
解释:
5 的二进制是 0b101 。

示例 3:

输入:6
输出:1
解释:
6 的二进制是 0b110 。

示例 4:

输入:8
输出:0
解释:
8 的二进制是 0b1000 。
在 8 的二进制表示中没有连续的 1,所以返回 0 。

提示:

  • 1 <= N <= 10^9

链接:https://leetcode-cn.com/contest/weekly-contest-93/problems/binary-gap/

分析:

首先将数据转换为二进制用vector存储起来,然后在存储数字vector中的1的坐标,新的坐标vector中相邻两个差值最大的就是最大距离。

如果0个数不到两个,则返回0

AC Code:

 class Solution {
public:
int binaryGap(int N) {
int ret = ;
vector<int> nums; //转换为二进制数字,存储每一位
while (N)
{
nums.emplace_back(N & 0x01);
N /= ;
}
vector<int> diss;//记录1的坐标
for (int i = ; i < nums.size(); i++)
{
if (nums[i] == )
{
diss.emplace_back(i);
}
}
if (diss.size() <= )
{
return ;
}
int f = diss[];
for (int i = ; i < diss.size(); i++)
{
ret = max(ret, diss[i] - diss[i - ]);
} return ret;
}
};

其他:

目前看不到用时最短code,第一code:

     class Solution {
public int binaryGap(int N) {
int prev = -;
int ret = ;
for(int i = ;i < ;i++){
if(N<<~i<){
if(prev >= ){
ret = Math.max(ret, i - prev);
}
prev = i;
}
}
return ret;
}
}
N<<~i<0,实际跑code看好像是将N低位开始从最高位逐步右移。
左移~0,即左移-1位等价于左移31位,获取到最低位是0还是1,
左移~1,即左移-2位,等价于左移30位,相当于获取二进制数据中的倒数第二位。
其实还是依次获得数据的低位是0还是1,和直接右移的区别是什么?

第一题:重新排序得到 2 的幂

问题:

从正整数 N 开始,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。

如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false

示例 1:

输入:1
输出:true

示例 2:

输入:10
输出:false

示例 3:

输入:16
输出:true

示例 4:

输入:24
输出:false

示例 5:

输入:46
输出:true

提示:

  1. 1 <= N <= 10^9

链接:https://leetcode-cn.com/contest/weekly-contest-93/problems/reordered-power-of-2/

分析:

如果将数字按照每位数字进行重新排列组合后检验是否是2的幂,一来比较复杂,二来位数多了后排列组合可能太多。反向思考下,知道数据“长度”,找到符合该长度的可能的2的幂的数字,然后数字按照大小重新排序,如果一致则说明能组成2的幂。

AC Code:

 class Solution {
public:
bool reorderedPowerOf2(int N) {
//先找到数字位数,得到该范围内的合法数据,每个数字单独排序,如果vector一致,则可以
bool ret = false;
vector<int> ornums;
int length = ;
while (N)
{
ornums.emplace_back(N % );
N /= ;
}
sort(ornums.begin(), ornums.end()); length = ornums.size();
vector<vector<int>> checks;
checks = getvalidnums(length);
int sameflag = true;
for (int i = ; i < checks.size(); i++)
{
if (checks[i].size() == length)
{
sameflag = true;
for (int j = ; j < checks[i].size(); j++)
{
if (checks[i][j] != ornums[j])
{
sameflag = false;
break;
}
}
//
if (sameflag == false)
{
continue;
}
else
{
return true;
}
}
}
return ret; }
vector<vector<int>> getvalidnums(int len)
{
vector<vector<int>> ret;
vector<int> tmp;
vector<int> tmpnum;
tmp = getvalidnum(len);
for (int i = ; i < tmp.size(); i++)
{
int tmpdata = tmp[i];
tmpnum.clear();
while (tmpdata)
{
tmpnum.emplace_back(tmpdata % );
tmpdata /= ;
}
sort(tmpnum.begin(), tmpnum.end());
ret.emplace_back(tmpnum);
}
return ret;
}
vector<int> getvalidnum(int len)
{
vector<int> ret;
int low = (int)pow(, len - );
int high = (int)pow(, len);
for (int i = ; (int)pow(, i) < high; i++)
{
if ((int)pow(, i) >= low)
{
ret.emplace_back((int)pow(, i));
}
} return ret;
} };

其他:

第一code:

         classcl  Solution {

         int[] freq(char[] s)
{
int[] f = new int[];
for(char c : s){
f[c-'']++;
}
return f;
} public boolean reorderedPowerOf2(int N) {
char[] s = Integer.toString(N).toCharArray();
int[] f = freq(s); for(long i = ;i <= <<;i*=){
int[] g = freq(Long.toString(i).toCharArray());
if(Arrays.equals(f, g))return true;
}
return false;
}
}

看起来像是JAVA,首先将数字转换为字符串s,然后转为数字数组f,f实际上记录的是0-9每个数字出现的个数。在1-1<<30 范围内(每次加倍),检测得到的数字i的数字数组(即组成数字的0-9每个的个数)是否和f一致。

第三题:优势洗牌

问题:

给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述。

返回 A 的任意排列,使其相对于 B 的优势最大化。

示例 1:

输入:A = [2,7,11,15], B = [1,10,4,11]
输出:[2,11,7,15]

示例 2:

输入:A = [12,24,8,32], B = [13,25,32,11]
输出:[24,32,8,12]

提示:

  1. 1 <= A.length = B.length <= 10000
  2. 0 <= A[i] <= 10^9
  3. 0 <= B[i] <= 10^9
 

链接:https://leetcode-cn.com/contest/weekly-contest-93/problems/advantage-shuffle/

分析:

目的是想要赢得场次多,类似田忌赛马,如果赢不了,直接拿最差的来应对。

首先将两个队伍按照实力排序,从强到弱AB对战,如果A能赢则迎战,否则A中最弱的来应对,A中的当前最强应对B的下一个。

AC Code:

 class Solution {
public:
vector<int> advantageCount(vector<int>& A, vector<int>& B) {
vector<int> ret;
vector<int> ShadowA(A);  //引用传递,避免修改到AB,其实用不到的
vector<int> ShadowB(B);
sort(ShadowA.begin(), ShadowA.end()); //先进行排序,方便对战
sort(ShadowB.begin(), ShadowB.end());
vector<pair<int, int>> battles; //
//vector<int> Aleft; //本来想要的是如果B中的某一个A中剩余部分没有人赢得了,跳过,结束后A中剩余部分直接和B中剩余部分随便匹配,反正打不过。不过提交出错后调试发现直接拿当前最弱的来应对就好了。
//vector<int> Bleft;
int ilow = ; //A中当前最弱的坐标
for (int i = ShadowA.size() - , j = ShadowB.size() - ; i >= ilow, j >= ;)
{ if (ShadowA[i] > ShadowB[j]) //能赢,进行匹配
{
pair<int, int> tmp{ ShadowB[j], ShadowA[i] };
battles.emplace_back(tmp);
i--;
j--;
//continue;
}
else
{
//Bleft.emplace_back(ShadowB[j]);
pair<int, int> tmp{ ShadowB[j], ShadowA[ilow] }; //打不过,直接拿A中最弱的一个来应对
battles.emplace_back(tmp);
ilow++;
j--;
//continue;
} } for (int i = ; i < B.size(); i++)   //将交战匹配对按照B中原有顺序排列输出A的出战顺序
{
for (int j = battles.size() - ; j >= ; j--)
{
if (battles[j].first == B[i])
{
ret.emplace_back(battles[j].second);
battles.erase(battles.begin() + j);
break;
}
}
} return ret;
}
};

其他:

第一code:

 class Solution {
public int[] advantageCount(int[] a, int[] b) {
int n = a.length;
int[][] bi = new int[n][];
for(int i = 0;i < n;i++){
bi[i] = new int[]{b[i], i};
}
Arrays.sort(bi, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
Arrays.sort(a);
int p = 0;
int[] ra = new int[n];
Arrays.fill(ra, -1);
boolean[] used = new boolean[n];
for(int i = 0;i < n;i++){
while(p < n && a[p] <= bi[i][0]){
p++;
}
if(p < n){
ra[bi[i][1]] = a[p];
used[p] = true;
p++;
}
}
int q = 0;
for(int i = 0;i < n;i++){
if(!used[i]){
while(q < n && ra[q] != -1)q++;
assert q < n;
ra[q] = a[i];
}
}
return ra;
}
}

还是java,不太懂而且没环境不太好调试查看,大概意思是对A进行排序,然后B中的每一个充A中找到最接近但比B大的数字来迎战?

第二用的是C++:

 class Solution {
public:
vector<int> advantageCount(vector<int>& a, vector<int>& b) {
int i,j,k,n,l;
vector<pair<int,int> > bb;
vector<pair<int,int> > aa;
vector<int> ans;
bb.clear();
n=a.size();
for (i=;i<n;i++)
bb.push_back(make_pair(b[i],i));
ans.clear();
for (i=;i<n;i++)
ans.push_back(-);
sort(a.begin(),a.end());
reverse(a.begin(),a.end());
sort(bb.begin(),bb.end());
reverse(bb.begin(),bb.end());
j=;
for (i=;i<a.size();i++)
{
while ((j<bb.size())&&(bb[j].first>=a[i])) j++;
if (j==bb.size()) break;
ans[bb[j].second]=a[i];
j++;
}
l=;
for (k=i;k<a.size();k++)
{
while ((l<ans.size())&&(ans[l]!=-)) l++;
ans[l]=a[k];
l++;
}
return ans;
}
};

第四题:最低加油次数

问题:

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。

沿途有加油站,每个 station[i] 代表一个加油站,它位于出发位置东面 station[i][0] 英里处,并且有 station[i][1] 升汽油。

假设汽车油箱的容量是无限的,其中最初有 startFuel 升燃料。它每行驶 1 英里就会用掉 1 升汽油。

当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。

为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回 -1 。

注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。

示例 1:

输入:target = 1, startFuel = 1, stations = []
输出:0
解释:我们可以在不加油的情况下到达目的地。

示例 2:

输入:target = 100, startFuel = 1, stations = [[10,100]]
输出:-1
解释:我们无法抵达目的地,甚至无法到达第一个加油站。

示例 3:

输入:target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]
输出:2
解释:
我们出发时有 10 升燃料。
我们开车来到距起点 10 英里处的加油站,消耗 10 升燃料。将汽油从 0 升加到 60 升。
然后,我们从 10 英里处的加油站开到 60 英里处的加油站(消耗 50 升燃料),
并将汽油从 10 升加到 50 升。然后我们开车抵达目的地。
我们沿途在1两个加油站停靠,所以返回 2 。

提示:

  1. 1 <= target, startFuel, stations[i][1] <= 10^9
  2. 0 <= stations.length <= 500
  3. 0 < stations[0][0] < stations[1][0] < ... < stations[stations.length-1][0] < target

链接:https://leetcode-cn.com/contest/weekly-contest-93/problems/minimum-number-of-refueling-stops/

分析:

最开始采用贪心策略,在当前能跑到的范围内找到油量最大的加油站,在那里加油,最后几分钟纯粹尝试下,当然失败了,局部的第二大未必就比另一个范围的最大值小。

当初做LeetCode的初衷本来就是长长见识,避免彻底废掉,上周的第四题折腾了好几个晚上,到现在92周总结都还没写,所以这次没准备纠结太多,稍微尝试了下,比如从起点开始,得到所有可能的路径,然后一直扩展

下去,最后得到所有能到达终点的策略,从中选择加油次数最小的。

比如给出的例子中,100/10, [[10,60],[20,30],[30,30],[60,40]]

初始油量10,[0,10],10范围内只有一个加油站没得选,{[0,10],[10,60]},当前位置10,油量60,可以到到极限70,剩下加油站都可以到达,下一次扩展结果

0/10+10/60+20/30:当前油量:80,位置20,剩余里程80

0/10+10/60+30/30:当前油量:70,位置30,剩余里程70

0/10+10/60+60/40:当前油量:50,位置60,剩余里程40

上面任意一个都可以到达目的地。

假设某一路线A一能够到达目的地,剩余部分只要已经加油次数超过A的次数,即可舍去。

但是这样涨下去可能爆内存,而且贪心时候给出的一个测例{ { 13, 21 }, { 26, 115 }, { 100, 47 }, { 225, 99 }, { 299, 141 }, { 444, 198 }, { 608, 190 }, { 636, 157 }, { 647, 255 }, { 841, 123 } };

尝试手动模拟,结果数据太多难以模拟,而且懒得折腾了,直接参考第一code。

做法是首先得到当前能到达的所有加油站,按照油量排序存储起来,在油量最多的那个里面加油,然后再根据当前位置以及油量,找到所有能够到达的位置,将加油站油量存储起来。

通过优先队列存储油量,这样的好处是自动在top位置存储当前油量最多的加油站,由于队列里面存储的加油站都是当前可达的,所以即使油量多的两个加油站是相邻的,也会在后面更新过程中用到,避免错过局部最大值。

在{ { 13, 21 }, { 26, 115 }, { 100, 47 }, { 225, 99 }, { 299, 141 }, { 444, 198 }, { 608, 190 }, { 636, 157 }, { 647, 255 }, { 841, 123 } }例子中,target 1000,初始油量299

首先第一次可达前5个加油站,按照油量排序:299/141,26/115,225/99,100/47,12/21,

选择299/141加油,此时位置299,油量299+141-299=141,剩余加油站[26/115,225/99,100/47,12/21],能够到达最远距离299+141=440(其实最远距离就是油量累加和),没有新的可以到达的加油站,从剩余加油站中选择油量最大的,即26/115,

当前能够到达440+115=555位置,新增加油站444/198,插入进去,当前剩余加油站[444/198,225/99,100/47,12/21],选择最大油量198,

则当前位置444,能够到达最远距离299+141+115+198=753,新增加油站后剩余加油站 [647/255,608/190,636/157,225/99,100/47,12/21 ],选择最大油量647/255

则此时能到达最远距离753+255=1008,达到target1000,则最终选择的加油站是26/115,299/141,444/198,647/255,即需要加油4次。

AC Code:

 class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
priority_queue<int> queue;
int ret = ;
int p = ; //加油站下标
int d = startFuel; //当前能到达的位置
while (true)
{
while (p < stations.size() && stations[p][] <= d) //将当前能到达的加油站都存储起来
{
queue.push(stations[p][]);
p++;
}
if (d >= target) //当前油量能够到达终点
{
return ret;
}
if (queue.empty() == )
{
return -;
}
d += queue.top(); //在能到达的加油站中取油量最大的一个
queue.pop();
ret++;
}
}
};

其他:

1.需要熟悉STL 中的一些基本性质,比如C++中priorty_queue是大堆,Java中貌似是最小堆,所以第一的code中需要存储-XXX来变相将小堆当做大堆用。

2.了解贪心算法的局限性

3.需要提高建模能力,好多问题本质上都是数学问题。

总结:

答出了三题,不过这一次题目相对简单,之前一次答出三题,提交错误好几次都能200+名,这次就提交错误两次都600+名了,虽然LeetCode周赛只是用来练习,能够排名靠前也是好的,难题要能做出来,简单题要能做的快。就目前个人能力来说,15+20+20+35的时间分配比较合理,而且一般来说最后30分钟还基本上都用到了前面三个题中,希望年前能够AK一次。

LeetCode之Weekly Contest 93的更多相关文章

  1. LeetCode之Weekly Contest 102

    第一题:905. 按奇偶校验排序数组 问题: 给定一个非负整数数组 A,返回一个由 A 的所有偶数元素组成的数组,后面跟 A 的所有奇数元素. 你可以返回满足此条件的任何数组作为答案. 示例: 输入: ...

  2. LeetCode之Weekly Contest 91

    第一题:柠檬水找零 问题: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10  ...

  3. LeetCode之Weekly Contest 90

    LeetCode第90场周赛记录 第一题:亲密字符串 问题: 给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true :否则返回  ...

  4. LeetCode之Weekly Contest 101

    前一段时间比较忙,而且做这个对于我来说挺耗时间的,已经间隔了几期的没做总结了,后面有机会补齐.而且本来做这个的目的就是为了防止长时间不做把编程拉下,不在追求独立作出所有题了.以后完赛后稍微尝试下,做不 ...

  5. LeetCode之Weekly Contest 92

    第一题:转置矩阵 问题: 给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9] ...

  6. LeetCode Weekly Contest 8

    LeetCode Weekly Contest 8 415. Add Strings User Accepted: 765 User Tried: 822 Total Accepted: 789 To ...

  7. Leetcode Weekly Contest 86

    Weekly Contest 86 A:840. 矩阵中的幻方 3 x 3 的幻方是一个填充有从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等. 给定一个 ...

  8. leetcode weekly contest 43

    leetcode weekly contest 43 leetcode649. Dota2 Senate leetcode649.Dota2 Senate 思路: 模拟规则round by round ...

  9. LeetCode Weekly Contest 23

    LeetCode Weekly Contest 23 1. Reverse String II Given a string and an integer k, you need to reverse ...

随机推荐

  1. NSPhotoLibraryAddUsageDescription解决办法

    图片并保存到本地的功能,一点发现闪退了.发现 Xcode 报以下错误: The app's Info.plist must contain an NSPhotoLibraryAddUsageDescr ...

  2. [LOJ 2039] 「SHOI2015」激光发生器

    [LOJ 2039] 「SHOI2015」激光发生器 链接 链接 题解 分为两个部分 第一个是求直线之间的交点找到第一个触碰到的镜面 第二个是求直线经过镜面反射之后的出射光线 第一个很好做,第二个就是 ...

  3. [NWPU2016][寒假作业][正常版第三组]搜索和二分 N

    题意,一条数轴上,告诉你起点和终点,只能向前走1,向后走1,或者走到二倍的现在的位置,每次都耗时一分钟.问从起点到终点的最短时长. 简单地bfs #include <iostream> # ...

  4. FusionCharts的类 - 实例功能

    一.FusionCharts的类 - 实例功能 1.configure(name:string , value:string)  or  configure(configurations: Objec ...

  5. TDH-search汇报理解

    题目:海量数据查询开头:1.自我介绍:2.题目切入: 什么是海量数据查询?(海量数据,快速,符合要求) 几个常用场景(搜索引擎,百度:话单查询:影像平台,高铁)3.展示目录:架构,案例,平台规划 4. ...

  6. Oracle ERP Interface堵住--Request Running too long time,查找Request执行的Sql

    Request Running too long time 堵住了INV Manager 导致INV Interface Pending 很多笔资料 Review 发现Request 实际执行SQL ...

  7. MyBatis配置文件之properties属性

    MyBatis提供3个方式使用properties: 1.property子元素. 2.properties文件. 3.程序代码传递. properties属性系给系统配置一些运行参数,一般放在XML ...

  8. 问题:java.sql.SQLException: No value specified for parameter 1

    解决方案:没有指定参数 String user = req.getParameter("user"); String pwd = req.getParameter("pw ...

  9. Ubuntu 11.04源

    ##国内源#这个北京交通大学的源也挺不错的,我们首选这个,速度很不错deb http://mirror.bjtu.edu.cn/ubuntu/ narwhal multiversedeb http:/ ...

  10. iOS-Swift相比Objective-C有哪些优缺点

    Swift,是苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序.它是一款易学易用的编程语言,而且 ...