LeetCode Day 13
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
思路:
因为是有序数组,设置一个max,当前走到哪个值了,后续的值比它小或者等于它,那都是重复值,抛弃该位即可。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
let max = Number.NEGATIVE_INFINITY;
let cursor = 0;
while (cursor < nums.length) {
if (nums[cursor] <= max) {
//重复了,抛弃它
nums.splice(cursor, 1);
}
else {
//新值
max = nums[cursor];
cursor++;
}
}
return nums.length;
};
执行用时 :88 ms
,在所有 JavaScript 提交中击败了65.71%
的用户
内存消耗 :38 MB
,在所有 JavaScript 提交中击败了8.44%
的用户
似乎空间消耗的还是比较大,大概是因为splice每次都创建了一个返回数组,虽然我这里没有任何变量引用它,想减少空间的使用量,那我们只好考虑出现重复值的时候,在找到一个不重复的数值之前,把后续的数组往前移动若干位置覆盖它即可。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
if (!nums || nums.length === 0) return 0;
let validCount = nums.length;
let duplicate = 0;
for (let i = 0; i < validCount; i++) {
while (i + 1 + duplicate < validCount && nums[i] === nums[i + 1 + duplicate]) {
duplicate++;
}
if (duplicate > 0) {
//将后续的数据往前移动
for (let j = i + 1 + duplicate; j < validCount; j++) {
nums[j - duplicate] = nums[j];
}
}
validCount -= duplicate;
duplicate = 0;
}
return validCount;
};
执行用时 :188 ms
,在所有 JavaScript 提交中击败了14.89%的用户
内存消耗 :37.2 MB
,在所有 JavaScript 提交中击败了38.56%的用户
只引入了两个常数变量,空间复杂度没什么变化,数组的移动上导致几乎多了一倍有余的时间,而空间仅仅节省了0.8MB,完全得不偿失。
我们试试官方题解:
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
if (!nums || nums.length === 0) return 0;
if (nums.length == 0) return 0;
let i = 0;
for (let j = 1, lens = nums.length; j < lens; j++) {
if (nums[j] != nums[i]) {
i++;
nums[i] = nums[j];
}
}
return i + 1;
};
执行用时 :64 ms
, 在所有 JavaScript 提交中击败了99.92%
的用户
内存消耗 :37.2 MB
,在所有 JavaScript 提交中击败了38.25%
的用户
这个做法的关键点在于,j一直往后找,找到一个不跟当前重复的值,就直接插入到当前位置之后,其实它只是找下一个比当前大的值,插入到前面的值之后而已,而不是后续的整体部分集体往前移动。
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例:
给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。
参考0026这道题的官方解法,我们很容易可以得出以下的代码:
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function (nums, val) {
let cur = -1;
for (let next = 0, lens = nums.length; next < lens; next++) {
if (nums[next] !== val) {
cur++;
nums[cur] = nums[next];
}
}
return cur + 1;
};
执行用时 :72 ms
, 在所有 JavaScript 提交中击败了33.58%
的用户
内存消耗 :34.2 MB
, 在所有 JavaScript 提交中击败了5.04%
的用户
空间的话只是两个常数指针变量差不了多少,但是时间确实可以优化一下。
考虑到nums=[5,1,2,3,4],然后val=5的情况,上面的写法就需要将后续的1,2,3,4都依次往前面赋值1次,一共赋值4次。
因为题目不要求数组的顺序,如果我们发现某个值不满足需要,我们可以直接把它跟数组最后一个进行交换,然后将有效的数组长度减少1,这样可以减少数字的移动次数和赋值次数。
/**
* @param {number[]} nums
* @param {number} val
* @return {number}
*/
var removeElement = function (nums, val) {
let current = 0;
let validLens = nums.length;
while (current < validLens) {
if (nums[current] === val) {
nums[current] = nums[validLens - 1];
validLens--;
} else {
current++;
}
}
return current;
};
执行用时 :64 ms
,在所有 JavaScript 提交中击败了76.40%
的用户
内存消耗 :34.2 MB
,在所有 JavaScript 提交中击败了5.04%
的用户
LeetCode Day 13的更多相关文章
- 【LeetCode算法-13】Roman to Integer
LeetCode第13题 Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symb ...
- 【一天一道LeetCode】#13. Roman to Integer
一天一道LeetCode系列 (一)题目 Given a roman numeral, convert it to an integer. Input is guaranteed to be with ...
- [LeetCode] 12,13 整数和罗马数互转
12. 整数转罗马数字 题目链接:https://leetcode-cn.com/problems/integer-to-roman/ 题目描述: 罗马数字包含以下七种字符: I, V, X, L,C ...
- C# 写 LeetCode easy #13 Roman to Integer
13.Roman to Integer Roman numerals are represented by seven different symbols: I, V, X, L, C, D and ...
- LeetCode题解(13)--Roman to Integer
https://leetcode.com/problems/roman-to-integer/ 原题: Given a roman numeral, convert it to an integer. ...
- python刷LeetCode:13. 罗马数字转整数
难度等级:简单 题目描述: 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值I 1V 5X 10L 50C 100D 500M 1000例如, 罗马数字 2 写做 II ...
- leetcode算法13.罗马数字转整数
哈喽!大家好,我是[学无止境小奇],一位热爱分享各种技术的博主! [学无止境小奇]的创作宗旨:每一条命令都亲自执行过,每一行代码都实际运行过,每一种方法都真实实践过,每一篇文章都良心制作过. [学无止 ...
- 算法练习之leetcode系列1-3
1.Reverse Words in a String public class Solution { public String reverseWords(String s) { String re ...
- 【LeetCode】13. Roman to Integer 罗马数字转整数
题目: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from ...
- 【leetcode】13. Roman to Integer
题目描述: Given a roman numeral, convert it to an integer. 解题分析: 这道题只要百度一下转换的规则,然后着这解释写代码即可.实现上并没有什么难度,直 ...
随机推荐
- art-template常用总结
高性能JavaScript模板引擎原理解析:http://cdc.tencent.com/2012/06/15/%E9%AB%98%E6%80%A7%E8%83%BDjavascript%E6%A8% ...
- RedHat无法使用yum源问题
RedHat下的yum是需要注册才能使用的 使用的话会提示: [root@test ~]# yum clean all Loaded plugins: product-id, refresh-pack ...
- BSC软件交流-BS
管理体系的提升公司.部门 关键指标 体系EXCEL记录的方式 较老,不够系统化BSC模式 测评.咨询.绩效软件目标地图 ,任务 目标 分解 平台?手机端? 集成 钉钉? paas平台?基础数据的获取团 ...
- 吴裕雄--天生自然Linux操作系统:Linux 磁盘管理
Linux磁盘管理好坏直接关系到整个系统的性能问题. Linux磁盘管理常用三个命令为df.du和fdisk. df:列出文件系统的整体磁盘使用量 du:检查磁盘空间使用量 fdisk:用于磁盘分区 ...
- java8新特性-函数式接口详细讲解及案例
一.函数式接口 1.1 概念 函数式接口在Java中是指:有且仅有一个抽象方法的接口.函数式接口,即适用于函数式编程场景的接口.而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适 ...
- vue wangeditor3封装
<script src="wangEditor/3.1.1/wangEditor.min.js"></script> Vue.component('my ...
- Python笔记_第三篇_面向对象_8.对象属性和类属性及其动态添加属性和方法
1. 对象属性和类属性. 我们之前接触到,在类中,我们一般都是通过构造函数的方式去写一些类的相关属性.在第一次介绍类的时候我们把一些属性写到构造函数外面并没有用到构造函数,其实当时在写的时候,就是在给 ...
- 如何选择开源项目的license
https://choosealicense.com/ http://www.csdn.net/article/2013-07-16/2816249-Github-Open-Source-Licens ...
- 蓝桥杯 sine之舞(递归)
Description 最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功.所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力.不妨 ...
- Python——Pandas 时间序列数据处理
介绍 Pandas 是非常著名的开源数据处理库,我们可以通过它完成对数据集进行快速读取.转换.过滤.分析等一系列操作.同样,Pandas 已经被证明为是非常强大的用于处理时间序列数据的工具.本节将介绍 ...