第一部分:数组
88.合并两个有序数组
题目:
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:**最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
第一种思路: 直接将两个数组进行合并,然后重新使用Arrays类的方法sort进行排序
class Solution {
public static void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i = m + n -1;i > m - 1;i--,n--){
nums1[i] = nums2[n-1];
}
Arrays.sort(nums1);
}
}
//或者上面的for语句可以使用Java中用于数组拷贝的方法之一:System.arraycopy(nums2,0,nums1,m,n),具体而言,它表明将数组nums2中的元素从索引0开始,拷贝到数组nums1的索引从m开始的位置,拷贝的元素个数为n个。这会覆盖nums1中相应位置的元素。
注意:第二种和第三种方法都可以再定义第三个指针,用于存放要放入的数据
第二种思路: 使用两个指针,同时创建一个大小为Nums1.length的数组temp,然后指针分别指向两个nums数组的第一个元素,比较两个指针指向的元素,较小的元素放入temp数组中,最后根据要求,令nums1指向temp
class Solution {
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int[] temp = new int[m+n];
System.arraycopy(nums1,0,temp,0,m);
//拷贝nums1到temp中,题目要求输出nums1
int p = 0;
int p1 = 0;
int p2 = 0;
while(p1<m && p2<n){
if(temp[p1]<=nums2[p2])
nums1[p++] = temp[p1++];
else
nums1[p++] = nums2[p2++];
}
while(p1<m)
nums1[p++] = temp[p1++];
while(p2<n){
nums1[p++] = nums2[p2++];
}
}
第三种思路(第二种方法的改进): 同样使用两个指针,但是不用再额外创建数组,这时指针指向两个数组实际的最后一个元素(按照上面的实例,nums1指向3,nums2指向6),然后比较大小,较大的元素放入到从后往前的nums1中
class Solution {
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int p = m + n - 1,p1 = m - 1,p2 = n - 1;
while(p1 >= 0 && p2 >= 0){
if(nums1[p1] > nums2[p2])
nums1[p--] = nums1[p1--];
else
nums1[p--] = nums2[p2--];
}
while(p1 >= 0)
nums1[p--] = nums1[p1--];
while(p2 >= 0)
nums1[p--] = nums2[p2--];
}
}
169. 多数元素
题目:
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
第一种思路:
暴力直接统计这个数组中各数字出现的次数,可以使用字典的形式采用HashMap集合,最后根据题目的意思,返回值是一个int,这里我感觉题目不严谨,返回值当然可以不止一个呢(修改也很简单,就略过了),不过按题目意思找到一个就直接break吧,这里可以复习一下:
这里还可以注意下:泛型类型不能使用基本数据类型作为类型参数。因此,
HashMap<int, int>
是不合法的在 Java 中,可以使用不同的方式遍历 HashMap。以下是两种常见的遍历方式:
使用
keySet()
方法遍历键,然后通过键获取对应的值:for (String key : map.keySet()) { System.out.println(key + " : " + map.get(key)); }使用
entrySet()
方法遍历键值对:for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + " : " + entry.getValue()); }
map.entrySet()
返回一个包含键值对的 Set 集合,每个元素都是 Map.Entry 对象,代表了 HashMap 中的一个键值对。- 在循环中,
Map.Entry
指定了这个键值对的类型,其中String
是键的类型,Integer
是值的类型。- 循环内部可以通过
entry.getKey()
来获取当前键值对的键,通过entry.getValue()
来获取当前键值对的值。这种方式遍历 HashMap 的好处是可以同时访问键和值,代码简洁清晰。如果需要遍历 HashMap 中的所有键值对,这种方式是推荐的使用方式。
class Solution {
public int majorityElement(int[] nums) {
int l = nums.length/2;
int re = 0;
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
if(map.containsKey(nums[i]))
//map.get(nums[i])++;在Java中,map.get(nums[i])++ 这种写法是无效的,
//因为 map.get(nums[i]) 返回的是一个值,而不是一个引用。
//不能直接对这个值进行自增操作。
map.put(nums[i], map.get(nums[i]) + 1);
else
map.put(nums[i],1);
}
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if(entry.getValue() > l){
re = entry.getKey();
break;
}
}
return re;
}
}
第二种思路(Boyer-Moore 投票算法):
如果我们把众数记为 +1,把其他数记为 −1,将它们全部加起来,显然和大于
0
,从结果本身我们可以看出众数比其他数多。我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
然后遍历这个数组,首先判断count的值,如果count为0,就把nums数组的元素x赋值给candidate,然后再判断x是否等于candidate,这里当count为0时是先赋值再判断是否相等,所以赋完值后count再加1,如果x不等于candidate,则count减去一,当count再次为0时则再次赋值......
再遍历完成后,这个candidate就是多数元素(众数)
或者
可以通过一个事实理解:如果一个数组有大于一半的数相同,那么任意删去两个不同的数字,新数组还是会有相同的性质。
注意是删除两个不同的数字
class Solution {
public int majorityElement(int[] nums) {
int candidate = 0;
int count = 0;
for(int i = 0; i < nums.length; i++){
if(count == 0)
candidate = nums[i];
if(candidate==nums[i]){
count++;
}else{
count--;
}}
return candidate;
}}
//此处代码的语句优化上,可以将for(int i = 0; i < nums.length; i++)换为:for (int num : nums),直接遍历数组的元素,同时简单的if,else语句可以使用三元运算符进行替换,如此处可以改为:
//count += (candidate==nums[i]) ? 1 : -1
//最后代码可以精简为:
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}}
开始刷算法,也是为了监督自己~~