本周刷的题有选择地写了题解,前半周写了很多二分查找问题和一些其他随机题目(闲来无事),后半周主要集中做顺序表的前缀和类型的题目。

#1685 有序数组中差绝对值之和

犯傻了!!没有仔细审题,题目里是本身有序的,其实就是简单前缀和加前后不同情况分类讨论,前边的一定小于当前nums[i],所以绝对值差之和就是(i+1)*nums[i]-presum[i];后边的值大于当前nums[i],绝对值差之和就是presum[nums.length-1]-presum[i]-nums[i]*(nums.length-1-i);两者相加就可!代码如下:

class Solution {public int[] getSumAbsoluteDifferences(int[] nums) {int sum = 0;int[] prefixSum = new int[nums.length];//计算前缀和for(int i=0;i<nums.length;i++){sum += nums[i];prefixSum[i] = sum;}//计算每个数的差绝对值之和int[] output = new int[nums.length];for(int i=0;i<nums.length;i++){// int sumOfLeftDifferences = (i+1)*nums[i]-prefixSum[i]; // int sumOfRightDifferences = prefixSum[nums.length-1]-prefixSum[i]-nums[i]*(nums.length-1-i);// sumOfDifferences =  sumOfLeftDifferences+sumOfRightDifferences;output[i] = (i+1)*nums[i]-prefixSum[i]+ prefixSum[nums.length-1]-prefixSum[i]-nums[i]*(nums.length-1-i);}return output;}
}

#1508 子数组和排序后的区间和

前缀和+排序,就是暴力解决的暂时也没有其他好思路。(简单浏览了一下其他人题解,貌似有双指针+二分查找解决)

class Solution {public int rangeSum(int[] nums, int n, int left, int right) {int[]sum=new int[n*(n+1)/2];int index=0;final int length=(int)1e9+7;//最大限度;for(int i=0;i<nums.length;i++){int s=0;for(int j=i;j<nums.length;j++){s+=nums[j];sum[index++]=s;}}Arrays.sort(sum);int ans=0;for(int i=left-1;i<right;i++){ans=(ans+sum[i])%length;}return ans;}
}

#1423 可获得的最大点数

前缀和加滑动窗口(掌握的不是很好,主要没接触过只做过类似的有一题提到了滑动窗口,当时也没细看,知识点还是快速掌握的好)。这题用了逆向思维,要获得外边k个的最大点数和,我们用一个滑动窗口length-k,只要保证我们窗口内最小,那么外边一定最大。

class Solution {public int maxScore(int[] cardPoints, int k) {int len=cardPoints.length,sum=0;for(int cardPoint:cardPoints){sum+=cardPoint;//前缀和}int min=Integer.MAX_VALUE,temp=0;int length=len-k;for(int i=0;i<len;i++){temp+=cardPoints[i];if(i>=length){//如果大于窗口范围temp-=cardPoints[i-length];//减去最外边的值,也就是窗口进行了滑动}if(i>=length-1)min=Math.min(min,temp);}return sum-min;}
}

#523 连续的子数组和

这题看似平常其实有好几个坑,都被我踩中了.....

首先这个连续的子数组要大于等于2。将这个数组连续前缀和算出,连续的子数组和肯定是不同前缀和相减,如果两个前缀和的余数相等,那么两个相减就是k的倍数(记住两个前缀和相差要大于1)

代码如下:

class Solution {public boolean checkSubarraySum(int[] nums, int k) {if(nums.length<2) return false;//长度小于2,直接返回falsefor(int i=0;i<nums.length-1;i++){if(nums[i]==0&&nums[i+1]==0) return true;//有前缀和为0,返回true}if(k==0) return false;if(k<0) k=-k;Map<Integer,Integer>map=new HashMap<>();//用一个哈希表储存位置map.put(0,-1);int sum=0;for(int i=0;i<nums.length;i++){sum+=nums[i];int mod=sum%k;if(map.containsKey(mod)){//mod相等if(i-map.get(mod)>1) return true;}elsemap.put(mod,i);//否则放入哈希表}return false;}
}

#42 接雨水

首先我自己做的思路就是找到左右两边最高的柱子中较小的柱子就是基准,用双指针实施,但具体细节方面有很多错误。然后思考了一下栈的运用,其实只要后边的比前边的低,并且再后边有高的柱子就能储水。

下边是双指针的官方题解:

其实就是看形成低洼的条件

class Solution {public int trap(int[] height) {int ans = 0;int left = 0, right = height.length - 1;//左右两个指针int leftMax = 0, rightMax = 0;while (left < right) {leftMax = Math.max(leftMax, height[left]);rightMax = Math.max(rightMax, height[right]);if (height[left] < height[right]) {//较小的在左边ans += leftMax - height[left];++left;} else {//较小的在右边ans += rightMax - height[right];--right;}}return ans;}
}

#1282 用户分组

贪心算法,注意各种结构的调用!

class Solution {public List<List<Integer>> groupThePeople(int[] groupSizes) {HashMap<Integer,Integer>count=new HashMap<Integer,Integer>();for(int i=0;i<groupSizes.length;i++){int size=groupSizes[i];count.put(size,count.getOrDefault(size,0)+1);}List<List<Integer>>result=new ArrayList<>();for(Map.Entry<Integer,Integer>entry:count.entrySet()){Integer key=entry.getKey();Integer value=entry.getValue();while(value>=key){List<Integer>list=new ArrayList<>();for(int i=0;i<groupSizes.length;i++){if(groupSizes[i]==key){list.add(i);groupSizes[i]=-1;if(list.size()==key){break;}}}result.add(list);value-=key;}}return result;}
}
#1608 特殊数组的特征值

找特殊数组的特征值,首先思路是找到数组的最大值,用一个新数组记录原数组每个数字的个数,从最大值处往0开始相加个数,如果相加的个数=该数字,证明就是特殊值,如果遍历完没有就返回-1;

class Solution {public int specialArray(int[] nums) {int maxval=0;//设定最大值for(int x:nums){if(x>maxval) maxval=x;//找最大值}int count[]=new int[maxval+1];//记数for(int x:nums){count[x]++;}int sum=0;for(int i=maxval;i>=0;i--){sum+=count[i];//sum就是大于i的个数if(sum==i) return i;//相等返回特殊值}return -1;}
}

#540 有序数组中的单一元素

明白异或运算的特性,异或满足交换律结合律,同时一个数和他本身异或为0,其他数和0异或还是本身,所以直接从头异或到尾得出的就是单一元素。(异或方法有序无序都可以用)

class Solution {public int singleNonDuplicate(int[] nums) {int ans=nums[0];for(int i=1;i<nums.length;i++){ans^=nums[i];}return ans;}
}

法二:二分查找法

才发现有序数组,并且规定了O(log n) 时间复杂度和 O(1) 空间复杂度。每个数都是两个,只有一个数唯一,则这个数左边必定是偶数个,右边也是偶数个,且左边肯定是nums[偶数]=nums[偶数+1],右边肯定是nums[奇数]=nums[奇数+1],所以二分如果nums[mid]==nums[mid^1](就是如果mid是偶数,nums[mid]==nums[mid+1],如果是奇数,nums[mid]==nums[mid-1])那么把left往右调,left=mid+1;(因为满足这种情况,证明单一的数必在右边)否则 right=mid;(在左边)

class Solution {public int singleNonDuplicate(int[] nums) {int l=0,r=nums.length-1;while(l<r){int mid=l+(r-l)/2;if(nums[mid]==nums[mid^1]) l=mid+1;else r=mid;}return nums[l];}
}

#349 两个数组的交集

用两个集合存储两个数组的值,然后在用集合数小的那个遍历,看另外一个集合是否有相同元素,如果有加入answer集合;

class Solution {public int[] intersection(int[] nums1, int[] nums2) {Set<Integer> set1 = new HashSet<Integer>();Set<Integer> set2 = new HashSet<Integer>();for (int num : nums1) {set1.add(num);}for (int num : nums2) {set2.add(num);}return getIntersection(set1, set2);}public int[] getIntersection(Set<Integer> set1, Set<Integer> set2) {if (set1.size() > set2.size()) {return getIntersection(set2, set1);}Set<Integer> intersectionSet = new HashSet<Integer>();for (int num : set1) {if (set2.contains(num)) {intersectionSet.add(num);}}int[] answer = new int[intersectionSet.size()];int index = 0;for (int num : intersectionSet) {answer[index++] = num;}return answer;}
}

#4 寻找两个正序数组的中位数  (好题)

首先题目要求算法的时间复杂度应该为 O(log (m+n)) 。我想到了二分法,怎么二分呢?中位数就是分割一串数字的数,中位数左边都小于中位数,中位数右边都大于中位数,我们要找到分割线,满足nums1,nums2左边最大值小于nums1,nums2右边最小值,那分割线上就是我们要找的中位数,设nums1上分割线位置为i,nums2上分割线位置为j,则i+j=(m+n+1)/2(合并了奇偶项保证中位数总在左边),然后进行二分查找,要满足nums1[i-1]<nums2[j]&&nums2[j-1]<nums1[i](i、j左右分别为小与大),所以不满足这个条件就缩小范围。最后找到分割线解决问题!

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int m=nums1.length,n=nums2.length;if(m>n) return findMedianSortedArrays(nums2,nums1);//以短的数组开始int total=(m+n+1)/2,left=0,right=m;while(left<right){int i=left+(right-left+1)/2;int j=total-i;if(nums1[i-1]>nums2[j]) right=i-1;//证明在i的左边else left=i;}int i=left,j=total-i;int nums1Leftmax=i==0?Integer.MIN_VALUE:nums1[i-1];//防止左边无的情况int nums2leftmax=j==0?Integer.MIN_VALUE:nums2[j-1];int num1rightmin=i==m?Integer.MAX_VALUE:nums1[i];int nums2rightmin=j==n?Integer.MAX_VALUE:nums2[j];if((m+n)%2==1) return Math.max(nums1Leftmax,nums2leftmax);else return (double)(Math.max(nums1Leftmax,nums2leftmax)+Math.min(num1rightmin,nums2rightmin))/2;}
}

#1385 两个​​​​​​组间的距离值

首先我想到的是直接模拟求解

class Solution {public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {int ans=0;for(int i=0;i<arr1.length;i++){int l=arr1[i]-d,r=arr1[i]+d,count=0;for(int j=0;j<arr2.length;j++){if(arr2[j]<l||arr2[j]>r) count++;}if(count==arr2.length){ans+=1;}}return ans;}
}

然后感觉可以二分解决,对arr1中的数,先对arr2排序,二分找到大于等于x的第一个数和小于x的第一个数,如果此时大于d,则其他必成立,此时小于d则删除。

class Solution {public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {int ans=0,m=arr1.length,n=arr2.length;Arrays.sort(arr2);//对arr2排序for(int x:arr1){int num=binarySearch(x,arr2);//二分查找最接近x的数boolean flag=true;if(num<n){flag&=arr2[num]-x>d;}if(num-1>=0&&num-1<=n){flag&=x-arr2[num-1]>d;}ans+=flag?1:0;//true就加1}return ans;}public int binarySearch(int x,int[]arr){int l=0,r=arr.length-1;if(x>arr[r]) return r+1;while(l<r){int mid=(r-l)/2+l;if(arr[mid]<x) l=mid+1;else r=mid;}return l;}
}

#670 最大交换

贪心算法:找到每个数字右边最大的数(必须大于这个数字) 然后返回,但是细节方面有很多要考虑的地方,提交了2次,第三次才全部考虑完全!可恶

class Solution {public int maximumSwap(int num) {String s=String.valueOf(num);char[]string=s.toCharArray();int[][]count=new int[s.length()][1];//用一个数组记录右边最大数字位置for(int i=0;i<s.length();i++){count[i][0]=findmax(string,string[i],i);//统计右边最大数字位置没有就为0if(count[i][0]!=0){int pos=count[i][0];if(string[i]!=string[pos]){//两个数字如果相等交换其实没有意义!char temp=string[i];string[i]=string[pos];string[pos]=temp;s=String.valueOf(string);num=Integer.valueOf(s);return num;}}}return num;}public int findmax(char[]string,char target,int start){int pos=0;char max=target;for(int i=start;i<string.length;i++){if(string[i]>=max){max=string[i];pos=i;}}return pos;}
}

#41 缺失的第一个正数

困难题,但思路很简洁,第一次遍历,让位置上的数字等于位置+1;第二次遍历,如果位置上的数!=位置+1,那么这个地方就是缺失的第一个正数,如果没有的话,就返回nums.length+1(证明原数组有1,2,3......nums.length)代码如下

class Solution {public int firstMissingPositive(int[] nums) {int n = nums.length;for (int i = 0; i < n; ++i) {while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {int temp = nums[nums[i] - 1];nums[nums[i] - 1] = nums[i];nums[i] = temp;}}for (int i = 0; i < n; ++i) {if (nums[i] != i + 1) {return i + 1;}}return n + 1;}
}

LeetCode一周题解(20220328-20220403)相关推荐

  1. 大工之星编程挑战赛第一周题解

    大工之星编程挑战赛第一周题解 总结 去年出了一车BUG,今年希望举办的时候希望没有BUG.最后看来,榜看起来还是很好看的,没有人AK,前排过的很多,后排也有题过.榜单也没有出现断层,算是成功了. 其实 ...

  2. LeetCode 554 砖墙 题解

    LeetCode 554 砖墙 题解 你的面前有一堵矩形的.由 n 行砖块组成的砖墙.这些砖块高度相同(也就是一个单位高)但是宽度不同.每一行砖块的宽度之和相等. 你现在要画一条 自顶向下 的.穿过 ...

  3. leetcode 贪心_leetcode题解(贪心算法)

    定义 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择. 也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解. 通常贪心算法的代码会非常短而且思路也非常 ...

  4. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第十周题解(个人向仅供参考)

    第10周 变量的作用域及编译预处理 1 求x的n次方(10分) 题目内容:编写求x的n次方的递归函数,在主函数调用并输出.(x为double型,n为整型,函数类型为double型) 输入格式: %lf ...

  5. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第五周题解(个人向仅供参考)

    第5周 循环结构程序设计 1 用for语句实现判断并求和.(10分) 题目内容: 求1~100以内 ( 包括100)能被3整除同时被5整除余数为1的所有数之和.要求用for语句完成. 输入格式: 无 ...

  6. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第十一周题解(个人向仅供参考)

    第11周 指针一 1 利用指针编写程序,统计字符串的长度.(10分) 题目内容:利用指针编写程序,统计字符串的长度.(不要使用求字符串长度函数) 输入格式: gets() 输出格式: "Le ...

  7. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第九周题解(个人向仅供参考)

    第9周 函数的定义及调用 1 编写函数,计算银行存款本息并输出.(10分) ** 题目内容: 编写函数计算银行存款本息,在主函数中从键盘输入银行存款金额(money).存款周期(year)和年利率(r ...

  8. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第十三周题解(个人向仅供参考)

    第十三周 结构与共用体 1 某班有5名同学,建立一个学生的简单信息表,包括学号.姓名.3门课程的成绩,编写程序,计算每名学生的平均成绩及名次.(30分) 题目内容: 某班有5名同学,建立一个学生的简单 ...

  9. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第三周题解(个人向仅供参考)

    第3周 数据的输入与输出 题1 交换两个变量(5分) 题目内容: 编写程序, 输入两个整型变量,交换两个变量的值,输出交换后的变量 输入格式: %d,%d 输出格式: %d,%d 输入样例: 3,4 ...

最新文章

  1. 【redis】2.redis可视化工具安装使用
  2. 一篇文章,带你了解 “机器学习工程师” 必备技能图谱
  3. 趣话题:同为技术岗,算法和开发哪个才是你的真命女神?
  4. 项目杂记——在后台获取Repeater控件里面的控件
  5. C#字节数组与值类型变量的互相转换,以及注意事项
  6. SiteServer CMS 新版本 V6.15(2020年6月1日发布)
  7. 大数据笔记-0907
  8. MySql命令——命令行客户机的分隔符
  9. “百度云手机”旗舰版发布,堪比旗舰真机?只需77元/月!
  10. 制作PC端的安装程序
  11. 近300个 Windows 10 可执行文件易受 DLL 劫持攻击
  12. 数组-scala数组与java的list的互转
  13. linux sys伪用户作用,linux用户管理详解
  14. 逻辑回归卡方拟合优度检验 r语言
  15. 这样投简历,HR一定会看
  16. 2014版C 语言程序设计基础,清华大学出版社-图书详情-《C/C++程序设计基础与实践教程》...
  17. 脑科学磁共振成像(MRI)初学者必看——功能脑网络、小世界网络、FDR校正、脑电信号频率变换、模板、假设检验、广义线性模型、独立成分分析、影像组学、任务态和静息态方法汇总
  18. Python自学之分子运动练习题
  19. Hamibot 基于AutoJs的自动化安卓app小程序赚钱神奇
  20. 基于Ant的Mentions自定义公式功能

热门文章

  1. 关于 《IT 专业应该怎么学》
  2. 利用requests库获取cookies的方式
  3. 亚马逊运营如何降低ACoS的5个技巧值得你收藏?
  4. Java C++ 实现第十二届蓝桥杯 C++ B组 省赛真题(希望能和各位佬能一起讨论算法题:讨论群:99979568)
  5. venus反光柱建图记录
  6. QT中的TS文件与QM文件
  7. 电信邮箱(@189.cn):启用IMAP/SMTP权限+登录密码
  8. WEB自动化_元素定位_elements与element_元素列表
  9. DCT变换-----学习笔记
  10. 菲鹏生物冲刺创业板上市:毛利率稳中有降,崔鹏、曹菲夫妇控股