2019.1.29 leetcode 刷题总结
题号:414
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
示例 1:
输入: [3, 2, 1]
输出: 1
解释: 第三大的数是 1.
示例 2:
输入: [1, 2]
输出: 2
解释: 第三大的数不存在, 所以返回最大的数 2 .
示例 3:
输入: [2, 2, 3, 1]
输出: 1
解释: 注意,要求返回第三大的数,是指第三大且唯一出现的数。
存在两个值为2的数,它们都排第二。
我的想法:
- 要求时间复杂度是O(n),也就是只能遍历一次数组,因此要遍历一次数组找出数组的最大值、第二大的值、第三大的值,对于重复出现的值要跳过,即三个值不应有相同的值;
- 遍历结束后,处理得到的三个值:首先要判断值Integer.MIN_VALUE是初始值还是数组中的值,因此需要一个boolean变量来标记数组中是否存在值Integer.MIN_VALUE
- 根据题目中的处理规则(有第三大的值返回第三大的值,没有返回最大值),给出返回值。
对应程序:
class Solution {
public int thirdMax(int[] nums) {
/*if(nums == null || nums.length == 0) {
return -1;
}*/
int max = Integer.MIN_VALUE;
int mid = Integer.MIN_VALUE;
int min = Integer.MIN_VALUE;
// 记录数组中是否含有值Integer.MIN_VALUE
boolean hasMinInteger = false;
// 遍历数组找出最大值、第二大的值和第三大的值,注意对于重复值的处理
for(int num : nums) {
// 判断数组中是否含有值Integer.MIN_VALUE
if(!hasMinInteger && num == Integer.MIN_VALUE) {
hasMinInteger = true;
}
if(num > max) {
min = mid;
mid = max;
max = num;
}else if(num > mid && num != max) {
min = mid;
mid = num;
}else if(num > min && num != mid && num != max) {
min = num;
}
}
// 判断min和mid中的值Integer.MIN_VALUE是初始值还是数组中的值
if(min == Integer.MIN_VALUE) {
if(mid == Integer.MIN_VALUE) {
return max;
}else {
if(hasMinInteger) {
return min;
}else {
return max;
}
}
}
return min;
}
}
题号:724
给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个
示例 1:
输入:
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释:
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。
示例 2:
输入:
nums = [1, 2, 3]
输出: -1
解释:
数组中不存在满足此条件的中心索引。
我的想法:
- 遍历数组的到数组的和sum;
- 在次遍历数组,记录当前元素左边的所有元素的和leftSum,当有(sum-nums[i])/2.0 == leftSum 时,返回此时的索引,即为中心索引;
- 一定要除以2.0以得到一个double类型的结果,换句话来说,当结果是小数时,一定不会是中心索引。
对应程序:
// java
class Solution {
public int pivotIndex(int[] nums) {
// 参数检查
if(nums == null || nums.length < 3) {
return -1;
}
// 求和
int sum = 0;
for(int num : nums) {
sum += num;
}
// 记录左边的和
int leftSum = 0;
for(int i = 0; i < nums.length; ++i) {
if(leftSum == (sum-nums[i])/2.0) {
return i;
}
leftSum += nums[i];
}
return -1;
}
}
题号:434
统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。
请注意,你可以假定字符串里不包括任何不可打印的字符。
示例:
输入: “Hello, my name is John”
输出:
我的想法:
- 看清题目,只要不是空格,所有连续的字符都算一个单词;
- 用空格分隔字符串,遍历字符串数组,记录长度不为零的字符串的个数,遍历结束返回该值。
对应程序:
// java
class Solution {
public int countSegments(String s) {
if(s == null || s.length() == 0) {
return 0;
}
String[] group = s.trim().split(" ");
int res = 0;
for(String temp : group) {
if(!"".equals(temp)) {
res++;
}
}
return res;
}
}
题号:654
集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。
给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入: nums = [1,2,2,4]
输出: [2,3]
我的想法:
- 将数组排序,遍历排序后的数组,找到相同的值,记录;
- 缺少的数字 = 未丢失元素的数组和 - 当前数组的和 + 重复的值;
对应程序:
// java
class Solution {
public int[] findErrorNums(int[] nums) {
int[] res = new int[2];
if(nums == null || nums.length == 0) {
return res;
}
Arrays.sort(nums);
int flagNum = nums[0];
int sum = flagNum;
for(int i = 1; i < nums.length; ++i) {
if(flagNum == nums[i]) {
// 记录相同的值
res[0] = flagNum;
}
flagNum = nums[i];
// 求和
sum += flagNum;
}
int n = nums.length;
int nSum = ((1 + n) * n)/2;
// 求解缺少的数字
res[1] = nSum - sum + res[0];
return res;
}
}
优化:
- 不使用排序,使用额外的数组空间temp[]存储该数组:将数组中的第i个值nums[i]当作temp的索引值,将nums[i]存入该索引位置,若temp[nums[i]] == 0,说明该位置还未被初始化,即这个位置还未出现重复元素,一旦有temp[nums[i]] != 0,即当前nums[i]为重复元素,记录该重复值;缺少的值同上面;
- 注意temp数组的大小要为nums.length + 1;
程序:
// java
class Solution {
public int[] findErrorNums(int[] nums) {
int[] res = new int[2];
// 参数检查
if(nums == null || nums.length == 0) {
return res;
}
// 记录nums数组的和
int sum = 0;
int[] temp = new int[nums.length + 1];
// 将nums数组中的第i个数nums[i]当作temp的索引
// 将nums[i]存入该索引位置
for(int i = 0; i < nums.length; ++i) {
// 如果该索引位置没被赋值
if(temp[nums[i]] == 0) {
// 将nums[i]存入该位置
temp[nums[i]] = nums[i];
// 如果该索引已经有值了,说明当前的nums[i]为重复值
}else {
// res数组记录该重复值
res[0] = nums[i];
}
// 记录nums数组的和
sum += nums[i];
}
int n = nums.length;
// 求未丢失元素前的数组的和
int nSum = ((1 + n) * n)/2;
// 缺少的值等于 未丢失元素前的数组的和 - 现在数组的和 + 重复的值
res[1] = nSum - sum + res[0];
return res;
}
}