2020/4/17
明天开始每日打卡计划
数组专题 simple
1
485. 最大连续1的个数
给定一个二进制数组, 计算其中最大连续1的个数。
示例 1:
输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.
思路:记录连续的个数,遇到0将计数清零
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int cnt = 0;
int max=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==1){
cnt++;
max=Math.max(max,cnt);
}else{
cnt=0;
}
}
return max;
}
}
2
219. 存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
示例 1:
输入: nums = [1,2,3,1], k = 3
输出: true
利用map的性质,若没有的数字将其放入字典中,否则取出比较距离,若符合则返回true,否则将当前的索引放入字典中,循环结束返回false;
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
int tmp = nums[i];
if(map.containsKey(tmp)){
int index=map.get(tmp);
if(i-index<=k)
return true;
map.put(tmp,i);
}else{
map.put(tmp,i);
}
}
return false;
}
}
3
643. 子数组最大平均数 I
给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。
示例 1:
输入: [1,12,-5,-6,50,3], k = 4
输出: 12.75
解释: 最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
思路:维护一个sum,初始化为前k个数字的和,求agv,然后从下标从k开始遍历,每次加上nums[i]-nums[i-k];取最大值,
class Solution {
public double findMaxAverage(int[] nums, int k) {
int n = nums.length;
int sum = 0;
double ans = 0;
for(int i=0;i<k;i++){
sum+=nums[i];
}
ans = sum*1.0/k;
for(int i=k;i<n;i++){
sum+=nums[i]-nums[i-k];
ans=Math.max(ans,(sum*1.0/k));
}
return ans;
}
}
4
605. 种花问题
假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。
示例 1:
输入: flowerbed = [1,0,0,0,1], n = 1
输出: True
思路:本题主要是要处理边界问题比较麻烦,如果数组长度为1,那么直接判断结果,否则先处理左边,如果如果边界为0,并且第二个位子为0,那么计数加1,否则,将索引直接加1,
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int index = 0;
int ans = 0;
int len = flowerbed.length;
if(len==1){
if(flowerbed[0]==0)
ans++;
return ans>=n;
}
while(index<len&&flowerbed[index]==1){
index++;
}
if(index==0&&flowerbed[1]==0){
flowerbed[0]=1;
ans++;
}
index++;
for(int i=index;i<len-1;i++){
if(flowerbed[i]==0&&flowerbed[i-1]==0&&flowerbed[i+1]==0){
flowerbed[i]=1;
ans++;
}
}
if(flowerbed[len-1]==0&&flowerbed[len-2]==0)
ans++;
return ans>=n;
}
}
5
674. 最长连续递增序列
给定一个未经排序的整数数组,找到最长且连续的的递增序列。
示例 1:
输入: [1,3,5,4,7]
输出: 3
解释: 最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。
比较简单
class Solution {
public int findLengthOfLCIS(int[] nums) {
if(nums.length==0)
return 0;
int cnt=1;
int max = 1;
for(int i=1;i<nums.length;i++){
if(nums[i]>nums[i-1]){
cnt++;
max=Math.max(cnt,max);
}else{
cnt=1;
}
}
return max;
}
}
6
1299. 将每个元素替换为右侧最大元素
给你一个数组 arr ,请你将每个元素用它右边最大的元素替换,如果是最后一个元素,用 -1 替换。
完成所有替换操作后,请你返回这个数组。
示例:
输入:arr = [17,18,5,4,6,1]
输出:[18,6,6,6,1,-1]
class Solution {
public int[] replaceElements(int[] arr) {
int n = arr.length;
int[] ans = new int[n];
ans[n-1]=-1;
int max = arr[n-1];
for(int i=n-2;i>=0;i--){
ans[i]=max;
max=Math.max(max,arr[i]);
}
return ans;
}
}
7
1013. 将数组分成和相等的三个部分
给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。
形式上,如果可以找出索引 i+1 < j 且满足 (A[0] + A[1] + … + A[i] == A[i+1] + A[i+2] + … + A[j-1] == A[j] + A[j-1] + … + A[A.length - 1]) 就可以将数组三等分。
示例 1:
输出:[0,2,1,-6,6,-7,9,1,2,0,1]
输出:true
解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
示例 2:
输入:[0,2,1,-6,6,7,9,-1,2,0,1]
输出:false
示例 3:
输入:[3,3,6,5,-2,2,5,1,-9,4]
输出:true
解释:3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
思路:先求和,若不是3 的倍数则直接输出false;否则遍历数组求和,当和为0的时候计数加1,结束以后判断计数是否大于等于3;是的话返回true;
class Solution {
public boolean canThreePartsEqualSum(int[] A) {
int sum =0;
for(int i=0;i<A.length;i++){
sum+=A[i];
}
if(sum%3!=0)
return false;
int agv = sum/3;
int cnt = 0;
int tmp =Integer.MIN_VALUE;
for(int i=0;i<A.length;i++){
if(tmp==Integer.MIN_VALUE){
tmp=0;
tmp+=A[i];
}else{
tmp+=A[i];
}
if(tmp==agv){
tmp=Integer.MIN_VALUE;
cnt++;
}
}
return cnt>=3;
}
}
8
414. 第三大的数
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
示例 1:
输入: [3, 2, 1]
输出: 1
解释: 第三大的数是 1.
思路:用三个变量来存放第一大,第二大,第三大的元素的变量,分别为one, two, three;
遍历数组,若该元素比one大则往后顺移一个元素,比two大则往往后顺移一个元素,比three大则赋值个three;
最后得到第三大的元素,若没有则返回第一大的元素。
class Solution {
private long MIN = Long.MIN_VALUE; // MIN代表没有在值
public int thirdMax(int[] nums) {
if (nums == null || nums.length == 0) throw new RuntimeException("nums is null or length of 0");
int n = nums.length;
int one = nums[0];
long two = MIN;
long three = MIN;
for (int i = 1; i < n; i++) {
int now = nums[i];
if (now == one || now == two || now == three) continue; // 如果存在过就跳过不看
if (now > one) {
three = two;
two = one;
one = now;
} else if (now > two) {
three = two;
two = now;
} else if (now > three) {
three = now;
}
}
if (three == MIN) return one; // 没有第三大的元素,就返回最大值
return (int)three;
}
}
9
566. 重塑矩阵
在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
示例 1:
输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
思路:先判断前后的总个数是否相等,即转换前后的行列乘积
class Solution {
public int[][] matrixReshape(int[][] nums, int r, int c) {
int row =nums.length;
int col=0;
if(row!=0)
col = nums[0].length;
if(row*col!=r*c)
return nums;
int aa = 0;
int bb = 0;
int[][] ans = new int[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
ans[i][j]=nums[aa][bb];
bb++;
if(bb%col==0){
bb=0;
aa++;
}
}
}
return ans;
}
}
10
1295. 统计位数为偶数的数字
给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。
示例 1:
输入:nums = [12,345,2,6,7896]
输出:2
解释:
12 是 2 位数字(位数为偶数)
345 是 3 位数字(位数为奇数)
2 是 1 位数字(位数为奇数)
6 是 1 位数字 位数为奇数)
7896 是 4 位数字(位数为偶数)
因此只有 12 和 7896 是位数为偶数的数字
class Solution {
public int findNumbers(int[] nums) {
int len = nums.length;
int ans = 0;
for(int i=0;i<len;i++){
int tmp = nums[i];
int cnt = 0;
while(tmp>0){
cnt++;
tmp=tmp/10;
}
if((cnt&1)==0)
ans++;
}
return ans;
}
}