leetcode刷题记录(414、724、434、654)

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的数,它们都排第二。

我的想法:

  1. 要求时间复杂度是O(n),也就是只能遍历一次数组,因此要遍历一次数组找出数组的最大值、第二大的值、第三大的值,对于重复出现的值要跳过,即三个值不应有相同的值;
  2. 遍历结束后,处理得到的三个值:首先要判断值Integer.MIN_VALUE是初始值还是数组中的值,因此需要一个boolean变量来标记数组中是否存在值Integer.MIN_VALUE
  3. 根据题目中的处理规则(有第三大的值返回第三大的值,没有返回最大值),给出返回值。

对应程序:

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
解释:
数组中不存在满足此条件的中心索引。

我的想法:

  1. 遍历数组的到数组的和sum;
  2. 在次遍历数组,记录当前元素左边的所有元素的和leftSum,当有(sum-nums[i])/2.0 == leftSum 时,返回此时的索引,即为中心索引;
  3. 一定要除以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”
输出:

我的想法:

  1. 看清题目,只要不是空格,所有连续的字符都算一个单词;
  2. 用空格分隔字符串,遍历字符串数组,记录长度不为零的字符串的个数,遍历结束返回该值。

对应程序:

// 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]

我的想法:

  1. 将数组排序,遍历排序后的数组,找到相同的值,记录;
  2. 缺少的数字 = 未丢失元素的数组和 - 当前数组的和 + 重复的值;

对应程序:

// 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;
    }
}

优化:

  1. 不使用排序,使用额外的数组空间temp[]存储该数组:将数组中的第i个值nums[i]当作temp的索引值,将nums[i]存入该索引位置,若temp[nums[i]] == 0,说明该位置还未被初始化,即这个位置还未出现重复元素,一旦有temp[nums[i]] != 0,即当前nums[i]为重复元素,记录该重复值;缺少的值同上面;
  2. 注意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;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值