[oj.leetcode] #179 - LargestNumber, 如何在7ms内跑完 221个测试用例

本地构建LeetCode链表相关测试用例 阅读详情

题目:已知一个整型数组,如何排列使得最后组成一个最大整数,输出这个整数的字符串,假设都是非负。

比如[3, 30, 34, 5, 9], 结果应该是 9534330

这里选用C++。

第一感觉应该是跟排序相关,稳妥方案是快速排序quick sort. 每两个数之间比较时,应从最高位开始,一位一位进行比较,将某一位更大的数排在前面。当然需要考虑当一个数是另一个数前缀时的情况,之后再说。

由于每两个数作比较时,每一位都可能参与比较,那么整型类型就显得很麻烦了,总不能一个数在每次比较时都去一位一位剥离出来。显然字符串是个好选择,比如将 123 转化成“123”, 那么我们可以在O(1)的时间内得到第i位[i]. 

慢着,多想一下,我们应该选用C风格字符串char*, 还是C++字符串string类型呢?对于[i] 操作显然没差别。问题在于之后的快速排序,因为是原地排序,所以会用到大量的交换函数,那么这里 char* 比 string 就有优势了,所以这里我选择C风格字符串char*。

继续思考两个数比较的问题,对于一个是另一个前缀,比如“12“, 与 “121“, 仔细想想,这其实是个递归,直到比较结束。

“12” ? “121”

a. "12" == "12(1)"

b. "12" ? "1" => "1" == "1"

c. "2" ? "1"    =>  "2" > "1"

所以,12 应该排在121前面,我们应该得到12121。

到此为止,我们已经把问题拆解的差不多了,另外还有些边缘情况,比如数组全0,仅一个非0等等。

完整的C++代码如下:

class Solution{
public:
    string largestNumber(vector<int> &num){
        int n = num.size();
        if(n < 1)    return string();
        vector<int> vec;
        char* seq[n];
        int lengths[n];
        int L = 0;    // total length of all char*
        bool allZero = true;
        for(int i=0; i<n; i++){ // init char* for int element
            int val = num[i];
            if(val == 0){
                vec.push_back(0);
            }else{
                allZero = false;
                while(val > 0){  // save 123 in vector<> as 3,2,1
                    vec.push_back(val % 10);
                    val /= 10;
                }
            }
            int l = vec.size();
            char* curr = new char[l+1];
            curr[l] = '\0';
            for(int j=0; j < l; j++){  // save reversed vec in curr
                curr[j] = '0' + vec[l-1 - j];
            }
            seq[i] = curr;
            lengths[i] = l;
            L += l;
            vec.clear();
        }
        if(allZero){  // all zero case is special
            for(int i=0; i<n; i++){
                delete[] seq[i];
                seq[i] = 0;
            }
            return string("0");
        }
        quick_sort(seq, n, lengths);
        // generate string from seq[]
        char result[L+1];
        result[L] = '\0';
        int t = 0;
        for(int i=0; i<n; ++i){
            for(int j=0; j < lengths[i]; ++j){
                result[t++] = seq[i][j];
            }
        }
        for(int i=0; i<n; i++){
            delete[] seq[i];
            seq[i] = 0;
        }
        return string(result);
    }

private:
    int compDeciFromHigh(char* decL, int nL, char* decR, int nR){
        int i=0;
        while(i < nL && i < nR){
            if(decL[i] != decR[i]){
                return decL[i] > decR[i] ? 1 : -1;
            }
            i++;
        }
        int res = 0;
        if(nL == nR)    return res;
        int deltaLen = max(nL, nR) - i;  // i == min(nL, nR)
        // next: compare the tail of long str and the short str
        if(i == nL){  // left str is short
            res = compDeciFromHigh(decL, nL, decR + nL, deltaLen);
        }else{  // right str is short
            res = compDeciFromHigh(decL + nR, deltaLen, decR, nR);
        }
        return res;
    }

    void quick_sort(char* seq[], int n, int* lengths){
        if(n < 2)    return;
        int p = 0, q = -1, t = n-1;
        while(p < t){
            if(compDeciFromHigh(seq[p], lengths[p],
                    seq[t], lengths[t]) > 0){  // move higher decimal ahead
                q++;
                swap_chpp(&(seq[q]), &(seq[p]));
                swap_ip(lengths + q, lengths + p);
            }
            p++;
        }
        q++;
        swap_chpp(&(seq[q]), &(seq[t]));
        swap_ip(lengths + q, lengths + t);

        quick_sort(seq, q, lengths);
        quick_sort(seq + (q+1), n-1 - q, lengths + (q+1));
        return;
    }

    void swap_chpp(char **p, char **q){
        char *tmp = *p;
        *p = *q;
        *q = tmp;
        tmp = 0;
    }

    void swap_ip(int *p, int *q){
        int tmp = *p;
        *p = *q;
        *q = tmp;
    }
};
代码有点长。除了开始阶段,要对每一个整型数转化得到字符串,另外我还用了一个数组来专门存放每个C风格字符串的长度,这样也好过回头用strlen() 再去量一遍每个的长度,代价就是在排序时,每次交换元素,也要对相应的长度元素作交换。

虽然看起来有点罗嗦,但事实证明一点一滴的优化都是值得的。最后这份代码实现在oj.leetcode的线上测试中,只用了7ms跑完了全部221个测试用例,这个成绩在所有提交代码中几乎也就是最好的了,有图为证:)

Ps, 对我而言,这份代码很好的诠释了C++语言相比于java/python在性能上的巨大优势。

leetcode查看测试用例-data-structures-binary-search-tree-starter:二叉搜索树的启动项目 leetcode 查看测试用例二叉搜索树项目 该项目包含一个框架,供您实现二叉搜索树。 这是一个测试驱动的项目。 运行测试并读取最上面的错误。 如果不清楚什么失败了,请打开test/test.js文件以找出测试预期的内容。 使最上面的测试通过。 继续使最上面的测试通过,直到所有测试都通过。 指示 从 克隆项目。 cd进入项目文件夹 npm install在项目根目录安装依赖 npm test运行规范 您可以在test/test.js查看测试用例。 你的工作是编写代码 lib/bst.js实现BST类 奖励:问题/04-leet-code-110.js作为一个便笺簿来解决 LeetCode.com 问题 奖励:问题/05-leet-code-108.js作为一个便笺簿来解决 LeetCode.com 问题 奖励:问题/06-leet-code-450.js作为一个便笺簿来解决 LeetCode.com 问题 立即下载

相关推荐

leetcode查看测试用例-algorithms-tabulation-project:练习制表策略的启动项目

leetcode 查看测试用例记忆问题 这个项目包含两个测试驱动的问题和一个在 LeetCode.com 上的问题。 从 克隆项目。 cd进入项目文件夹 npm install在项目根目录安装依赖 npm test运行规范 您可以在/test/test.js查看测试用例。 您的工作是在/lib文件中编写代码以通过所有规范。 在problems.js ,你会写代码,以使stepper , maxNonAdjacentSum和minChange功能通过。 在leet_code_64.js ,您将使用该文件作为草稿簿来解决 LeetCode.com 上的问题。 在leet_code_70.js ,您将使用该文件作为便笺簿来解决 LeetCode.com 上的问题。

编写leetcode测试用例时所用的辅助函数

在做leetcode题目(https://oj.leetcode.com/problemset/algorithms/)的时候,我们总要自己写测试用例,常常要生成vector, list, tree,我将这些常用操作封装了一下,方便大家使用

小豪之家 9231

windows系统下,如何为comfyui如何安装triton

​ 有些加速插件、模型在安装的时候,比如说sageattention的安装,就需要提前安装triton这个包,不过这个包有点特殊,windows下略微不好装,经常会装失败。 🎠如何安装 之前也有人介绍过,要到github上找个wheel文件,找到对应的版本安装下就好了。 问题是:https://github.com/woct0rdho/triton-windows/releases 这个git地址上,已经找不到wheel文件了... ​

聚梦小课堂 4497

springboot 单元测试-哪些静态的引入

package com.example.demo; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.notNullValue; import static org.springframework.test...

iechenyb专栏 901

获取本机正版windows10激活密钥,以及正版office

本方法面向的是以前买过笔记本电脑给你预装了正版系统,激活了正版office(一般是家庭版)的情况,其他情况请自行尝试。

qq_45774917的博客 2万+

无法联网的情况下,dbeaver离线安装数据库驱动-clickhouse

无法联网的情况下,dbeaver离线安装数据库驱动-clickhouse

u012831187的博客 1万+

leetcode测试用例转化数据库表

leetcode测试用例转化成数据库表脚本

weixin_44133605的博客 1503

gesp c++ 五级知识点

gesp c++ 五级知识点

MMD.然大大 2009

Leetcode上测试用例测试结果正确,但提交后有错的问题

问题说明:在leetcode上刷题的时候,有时候会出现,测试的时候没有错,但提交就错。这就很头疼了 这个问题我遇到几次,慢慢发现了其中的道理。分享给大家, 1、如果你的...

weixin_38072112的博客 4646

基于STM32F103C8T6的红外循迹避障小车

编程思路:控制核心板IO口的电平(即电机驱动模块的AIN1,AIN2,BIN1,BIN2)从而控制AO1、AO2、BO1、BO2的电平高低,进而控制电机使其正转、反转、不转。由于单纯地拉高拉低电平只能让电机在转与不转的状态切换,故决定利用TIM4的两个通道分别产生两路PWM信号来控制电机速度,四个电机两个一组,同一侧的两个连接在同一个PWM上。(#include "dianji.h"文件中同时写了对循迹模块引脚的初始化)

weixin_48743503的博客 1万+

PHP+MYSQL宠物主题动态网页设计源码+数据库,大学生期末大作业,PHP课程设计

PHP+MYSQL宠物主题动态网页设计源码+数据库,大学生期末大作业,PHP课程设计提示:本文采用PHP对数据库进行操作:本文就介绍了PHP实现对MySQL数据库的增删改查操作基础内容。

899

leetcode-164- 最大间距(快速排序+计数排序+基数排序+桶排序)

题目要求 给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。 如果数组元素个数小于 2,则返回 0。 示例 1: 输入: [3,6,9,1] 输出: 3 解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。 示例 2: 输入: [10] 输出: 0 解释: 数组元素个数小于 2,因此返回 0。 说明: 你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。 请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。

shadowgully的博客 297

LVGL colorwheel组件教程一(调色板)

【代码】LVGL colorwheel组件教程一(调色板)

摸鱼专家 429

Junit4 单元测试

1 环境:Myeclipse 2014(含Junit 4框架) 2Junit 4介绍 (1):测试类不一定要继承TestCase类; (2):测试方法函数原型为-public+ void+ 函数名();注:函数名不一定要以test开头; (3);测试方法前要有@Test 注解; 3例子分析 目录结构如下 注;largest包下有个目标类(被测试类)Largest.java(有个求

hello world 713

单反相机物镜设计[DG-10]

REAR(要打在像面,操作数要找像面对应位置15):以透镜单位表示的真实光线径向坐标,波长由Wave定义,参见“Hx、Hy、Px和Py”。最小玻璃厚度最小不能小于semi-dia的1/10,要根据layout看有没有过厚过薄,反复调节。PROD:两个操作数的乘积(操作#1 X操作#2)。3x4就是57.3x0.41=23.5。拦光一般在第一面和最后一面操作,减少边缘无用光线。光阑面与镜面贴近,要调距离,同时设置光阑像差。后截距是指从镜头后表面到焦点的距离。CONS:弧度转为角度。镜头相互嵌入,有错误。

weixin_72050316的博客 600

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

关于 Leetcode 上测试没错,提交有错的问题

问题说明:在leetcode上刷题的时候,有时候会出现,测试的时候没有错,但提交就错。这就很头疼了 这个问题我遇到几次,慢慢发现了其中的道理。分享给大家, 1、如果你的 c/c++ 尽可能不要使用全局变量,这个leetcode已经说明了 2、如果你是java,同时也使用了全局变量。 记住千万不要用 static 去修饰,在你的代码中不要出现 static, 3、你的代码写的真的有问...

小道仙的后宫 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

两个版本的快速排序

算法导论版和严蔚敏版

几百个测试用例一致通过 409

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LeetCode上读不懂题!看不懂测试用例的那些题(有生之年更新。。。)

两个列表的最小索引总和 假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。 示例 1: 输入: [“Shogun”, “Tapioca Express”, “Burger King”, “KFC”]...

csdn_kou的博客 1461

单元测试

单元测试是开发自己编写的针对代码某个功能模块验证其行为的测试单元模块;单元测试贯穿在开发的整个过程,并伴随着新功能模块的产生而进行;单元测试并不会花费更多的时间,与之相反,在提高代码效率、减少bug数量、有序开展开发工作上,单元测试发挥着很大的作用。

qq_39273039的博客 4291

单元测试-入门篇

前面的一篇文章(单元测试-理论篇)讨论了什么是单元测试、单元测试的优点并列举了很多不写单元测试的借口。如果你同意我们的观点,认同单元测试确实是软件开发中不可缺少的过程,那么我们就开始单元测试之旅吧!一个比较最大值的函数  我们首先引入一个比较最大值的函数。我们传入一个类型为int的数组参数,它将返回最大值的那个元素。代码如下:public class Largest { public static

moxie的专栏 1743

Android SO逆向中JNI环境怎么补?用JNItrace快速定位并模拟AssetManager等系统调用

本文详细解析了Android SO逆向中JNI环境补全的高效策略,重点介绍如何利用JNItrace工具快速定位关键系统调用,并在Unidbg中精准模拟AssetManager等复杂对象。通过动态追踪与精准模拟相结合的方法,大幅提升逆向分析效率,有效应对反调试等安全防护措施。

weixin_30839881的博客 1021

leetcode中,代码如何调试,创造本地运行环境

初次接触leetcode,是我在一个招聘网站上看的,这个OJ真有那么厉害吗? 这几天在这个OJ上做了几道题,发现他的几个特点,1、题目不难(相对于ACM来说,我被ACM虐到至今无力),评判没那么苛刻,2、十分基础,从链表、树到动态规划等,都是非常基本非常经典的内容,相当的靠基本功,3、没有本地调试环境,直接在网站上提交,后台评判系统帮你完成程序输入、评判输出的功能,4、国内外业内认可,有很多人都

bg2bkk的专栏 2万+

快速排序测试(QuickSort)

一. 目的 进行快速排序练习,掌握快速排序的原理。 算法证明: 第一步,数组分为四个区,无序小于关键值区A[1]-A[i],无序大于关键值区A[i+1]-A[j],待划分区A[j+1]-A[N-1],关键值区A[N],第一步时,只有两个区域不为空,即带划分区A[1]-A[N-1],关键值区A[N] 第二步:进入循环处理,若存在可以放在无序小区的元素,则将无序大区则将无序大区的下界元素与A[j

losteronly的博客 2142

LeetCode的使用方法

LeetCode 是一个上提供一系列的算法题,并且具备多种编程语言优秀在线编辑体验。在这样的基础之上,LeetCode 对于各类题目的描述简洁易懂,题库更新极快,最重要的是它的含金量受到大众的认可,拥有庞大的用户群体,对于每一道算法题基本能够寻找到较好的解题思路。特别说明的是,该平台更为着重对于算法思路的训练,采取的并非 ACM 模式的全包全揽,而是提供一个需要实现的函数,测试用例的定义和主方法的调用等等将由系统提供。 需要训练 ACM 模式的,可以尝试牛客网的刷题模式。 LeeCode 刷题思路 作为一个

yumuing‘s blog 1万+

【leetcode】513. 找树左下角的值(完整测试代码)

给定一个二叉树,在树的最后一行找到最左边的值。 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 思路:pair <层数,节点值> 先序遍历树...

Charles_ke的博客 466
上一篇: Python中yield的使用小述
下一篇: [oj.leetcode] #174 - Dungeon Game 一次特别的DP之旅
teaspring
博客等级 码龄19年 350粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值