题意:
实现
RandomizedSet
类:
RandomizedSet()
初始化RandomizedSet
对象bool insert(int val)
当元素val
不存在时,向集合中插入该项,并返回true
;否则,返回false
。bool remove(int val)
当元素val
存在时,从集合中移除该项,并返回true
;否则,返回false
。int getRandom()
随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为
O(1)
。
【输入样例】
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"] [[], [1], [2], [2], [], [1], [2], []]【输出样例】
[null, true, false, true, 2, true, false, 2]
解题思路:
数组+哈希表
1.随机获取一个元素平均时间复杂度为O(1),最好的就是数组;
2.插入和删除的平均时间复杂度为O(1),比较好的就是哈希表;
3.两者结合,因为哈希表中无法再O(1)时间内完成获取随机元素操作,所以数组中存储元素,哈希表中存储每个元素在数组中的下标;
4.因为元素个数随着样例不同而不同,所以使用变长数组。
5.因为元素val是唯一存储的是,所以哈希表中的key是val。
class RandomizedSet {
List nums;
Map indices;
Random random;
public RandomizedSet() {
nums = new ArrayList();
indices = new HashMap();
random = new Random();
}
public boolean insert(int val) {
if(indices.containsKey(val)){
return false;
}
int index = nums.size();
nums.add(val);
indices.put(val,index);
return true;
}
public boolean remove(int val) {
if(!indices.containsKey(val)){
return false;
}
int index = indices.get(val);//获取值val在数组中的下标
int last = nums.get(nums.size()-1);//获取数组最后一位的值
nums.set(index,last);//nums数组中index位置,值从val变成last
indices.put(last,index);//哈希表中,将指定的值index与此键last关联
nums.remove(nums.size()-1);//删掉最后一位
indices.remove(val);
return true;
}
public int getRandom() {
int randomIndex = random.nextInt(nums.size());
return nums.get(randomIndex);
}
}
时间: 击败了85.78%
内存: 击败了39.05%
题意:
在一条环路上有
n
个加油站,其中第i
个加油站有汽油gas[i]
升。你有一辆油箱容量无限的的汽车,从第
i
个加油站开往第i+1
个加油站需要消耗汽油cost[i]
升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组
gas
和cost
,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回-1
。如果存在解,则 保证 它是 唯一 的。
【输入样例】
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"] [[], [1], [2], [2], [], [1], [2], []]【输出样例】
[null, true, false, true, 2, true, false, 2]
解题思路:
1.定义两个指针,start指针指向从哪一加油站开始,count指针用于遍历数组
2. 定义变量resOil表示剩余的油量,通过判断来决定能否继续往下走
3.思路简单清晰,但是超时了哈哈哈哈哈
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int start = 0;
int resOil = 0;
int len = gas.length;
int count = 0;
while(start < len){//从哪个加油站开始
if((resOil += gas[count]) >= cost[count]){
resOil -= cost[count];
++count;
count %= len;
if(count%len == start){
return start;
}
}else{
++start;
count = start;
resOil = 0;
}
}
return -1;
}
}
勉强修改了一下代码,终于能通过了
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int start = 0;
int len = gas.length;
while(start < len){//从哪个加油站开始
int resOil = 0;
int count = 0;//总共走了几个站点
while(count < len){
int j = (start + count) % len;//环形加油站
resOil += gas[j];
resOil -= cost[j];
if(resOil<0){
//哦偶,油不够
break;
}
count++;//这个站点ok ok
}
if(count == len){
return start;
}else{
start = start + count + 1;//从不满足的站点开始检查
}
}
return -1;
}
}
时间: 击败了39.88%
内存: 击败了38.13%
题意:
罗马数字包含以下七种字符:
I
,V
,X
,L
,C
,D
和M
。字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000例如, 罗马数字
2
写做II
,即为两个并列的 1 。12
写做XII
,即为X
+II
。27
写做XXVII
, 即为XX
+V
+II
。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做
IIII
,而是IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。给定一个罗马数字,将其转换成整数
【输入样例】s="III"
【输出样例】3
解题思路:
1用map实现了
class Solution {
public int romanToInt(String s) {
Map map = new HashMap<>();
map.put('I',1);
map.put('V',5);
map.put('X',10);
map.put('L',50);
map.put('C',100);
map.put('D',500);
map.put('M',1000);
//小的数字在大的数字右边,直接加,如果小的数字在大的数字后面,需要减
int count = 0;
for(int i =0;i
时间: 击败了58.46%
内存: 击败了26.48%
题意:
与上面一题一样,但是是将整数转为罗马数字。
【输入样例】3
【输出样例】"III"
解题思路:
暴力匹配
class Solution {
public String intToRoman(int num) {
StringBuffer s = new StringBuffer();
int[] listNum = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
String[] listString = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int i = 0;
while(num > 0){
while(num - listNum[i] >=0){
s.append(listString[i]);
num -= listNum[i];
}
++i;
}
return s.toString();
}
}
时间: 击败了97.00%
内存: 击败了45.15%
题意:
给你一个字符串
s
,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
【输入样例】“hello world’
【输出样例】5
解题思路:
不用多说吧,从后开始遍历,找到第一个不是空格的字符,统计其到下一个空格的长度,因为题目说是单词组成,所以不用额外判断是否是字母。
class Solution {
public int lengthOfLastWord(String s) {
int total=0;
int i=s.length()-1;
while(s.charAt(i)==' '){
i--;
}
while(i >= 0 && s.charAt(i)!=' '){
total++;
i--;
}
return total;
}
}
时间: 击败了100.00%
内存: 击败了39.8%
bye~~ 吃饭去了