目录
1.获取数组中的主要元素
2.移动0元素至数组末尾
3.求两个整数数组的交集
4.计算X的算数平方根
5.找出只出现1次的数字
6.查找数组中的多数元素
7.计算Excel表列序号
8.种花问题
9.找出字符串中的最大值
10.移除元素
题目描述:数组中占比超过一半的元素称之为主要元素。给定一个 整数 数组,找出其中的主要元素。若没有,返回 -1
。
解:利用HashMap统计元素出现次数,遍历集合,当某个key的value大于数组长度的一半,返回该元素,否则返回-1。
public static int solve(int[] nums) {
HashMap map = new HashMap<>();
//遍历数组
for (int i=0,len=nums.length;ilen/2)
return key;//大于返回
}
}
//数组遍历结束还未返回,则返回-1
return -1;
}
问题描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序
解:对于非零元素,直接存入新数组,而0元素利用下标存入数组尾部
public static int[] solve(int nums[]){
//创建与原数组长度一致的数组
int resLen=nums.length;
int res[]=new int[resLen];
//遍历原数组
for(int i=0,len=nums.length,k=0;i
问题描述:给定两个数组 nums1
和 nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。
解:使用集合的contains方法解决交集问题,该方法用于判断参数元素是否存在于当前集合中。
使用HashSet解决值重复问题,对于一个数组,其值是有序且可以重复的,但最终的结果要求值唯一,因此选择HashSet过滤重复值
public static int[] intersection2(int[] nums1, int[] nums2) {
//需要使用集合的contains方法,将数组转换为集合
HashSet set1 = new HashSet<>();
//存放结果的set集合
HashSet res0 = new HashSet<>();
//遍历nums1,将其加入集合
for (int i : nums1) {
set1.add(i);
}
//遍历nums2时,开始比较,当该值包含在nums1中,则加入集合
for (int i : nums2) {
if(set1.contains(i)){
res0.add(i);
}
}
//将结果集合转换为数组返回
int index=0;
int[] res1=new int[res0.size()];
for (Integer num : res0) {
res1[index]=num;
index++;
}
return res1;
}
题目描述:给你一个非负整数 x ,计算并返回 x 的 算术平方根。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
解:4的算数平方根为2,9为3,由题可知,结果仅保留整数部分,因此对于大于4小于9的数,算数平方根均为2。所以只需要循环判断当前数字的平方是否大于目标数,大于时则说明结果为当前数-1
public static int mySqrt(int x) {
//特殊情况,直接返回
if(x==0){
return 0;
}
if(x==1){
return 1;
}
//循环判断
for(int i=2;i<=x;i+=i){
if(i*i==x){
return i;
}
if(i*i>x){
return i-1;
}
}
return -1;
}
题目描述:给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
解:方法1==>使用HashMap键值对存储每个元素出现的次数,最后遍历map找出值为1的元素返回。
方法2==>题目说除某元素外,其余元素均出现2两次,所以使用异或运算符,消除偶数次元素
//HashMap
public static int singleNumber1(int[] nums) {
HashMap map = new HashMap<>();
for (int num : nums) {
map.put(num,map.get(num)!=null?map.get(num)+1:1);
}
for (Integer keySet : map.keySet()) {
if(map.get(keySet).equals(1)){
return keySet;
}
}
return -1;
}
//异或
public static int singleNumber2(int[] nums) {
int res=0;
for (int i=0;i
题目描述:给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。可以假设数组是非空的,并且给定的数组总是存在多数元素。
解:对于出现次数大于n/2的元素,在排序后一定位于数组的中位
public static int majorityElementMore(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
题目描述:给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号
A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 ...
解:相当于计算26进制对应的十进制数,根据二进制转十进制的经验,只需要按权展开,就可以得到结果
public static int titleToNumber(String columnTitle) {
//colum用于保存最终结果
int colum=0;
for(int i=columnTitle.length()-1,k=0;i>=0;i--,k++){
//计算每一位的值
int c= (int) ((columnTitle.charAt(i)-64)*Math.pow(26,k));
colum+=c;
}
return colum;
}
问题描述:假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给你一个整数数组 flowerbed
表示花坛,由若干 0
和 1
组成,其中 0
表示没种植花,1
表示种植了花。另有一个数 n
,能否在不打破种植规则的情况下种入 n
朵花?能则返回 true
,不能则返回 false
。
解: 对于这样一个数组,有三种可能可以种花:
1.该位置在数组中下标为0,值为0,且后一个下标值也为0
2.该位置在数组中下标为lenth-1,值为0,且lenth-2的值也为0
3.该位置在数组中,值为0,且前一个后一个值都为0
因此只需要遍历数组,并将以上三种情况作为条件,当条件满足时,n--,当n<=0时返回true,否则false
特殊情况:该数组中仅有一个元素,此时无需判断他与前后的关系,只用判断值为0还是为1即可
public static boolean canPlaceFlowers(int[] flowerbed, int n) {
//处理特殊情况
int len = flowerbed.length;
if(len==1&&flowerbed[0]==0){
return true;
}
//遍历集合
for (int i = 0; i < len; i++) {//{1,0,0}
//判断下标为0的元素
if(i-1==-1&&flowerbed[i]==0&&flowerbed[i+1]==0){
flowerbed[i]=1;
n--;
}
//判断下标为1的元素
if(i+1==len&&flowerbed[i]==0&&flowerbed[i-1]==0){
flowerbed[i]=1;
n--;
}
//判断中间元素
if(i>1&&flowerbed[i]==0&&flowerbed[i-1]==0&&flowerbed[i+1]==0){
flowerbed[i]=1;
n--;
}
if(n<=0){
return true;
}
}
return false;
}
问题描述:一个由字母和数字组成的字符串的 值 定义如下:如果字符串 只 包含数字,那么值为该字符串在 10 进制下的所表示的数字。否则,值为字符串的 长度 。 给你一个字符串数组 strs ,每个字符串都只由字母和数字组成,请你返回 strs 中字符串的 最大值 。
解:对于这样一个数组中的字符串,只有两种情况,对于全数字的字符串,转换为整数,否则获取长度
方法1==>遍历字符数组,先判断长度或数值,再把结果存起来,比较之后得到最大值返回。比较麻烦,但是能做出来
方法2==>使用一个变量存储结果,每次获取到长度或值时都与该变量比较,循环结束返回,简单一些
//方法1
public static int maximumValue1(String[] strs) {
//定义存储结果的list集合
ArrayList list = new ArrayList();
//遍历字符串数组
for (String str : strs) {
boolean isNum =false;//先假设字符串中都是字母,如果该值变成true,则退出循环
for (int i = 0; i < str.length(); i++) {
isNum = str.charAt(i)>='0'&&str.charAt(i)<='9'?true:false;
break;
}
if(isNum){//此时不能确定该字符串是一个全数字的串还是一个混合的串
try {//那么当类型转换成功时,该串为全数字,否则混合,分别添加值和长度
int num=Integer.parseInt(str);
list.add(num);
} catch (NumberFormatException e) {
list.add(str.length());
}
}else{//当该字符串遍历结束,isNum还为false,说明该串全字母
list.add(str.length());//添加长度
}
}
//使用集合工具类的sort方法,自定义排序规则,从大到小
Collections.sort(list,new Comparator(){
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
//返回集合中第一个元素
return (int) list.get(0);
}
//方法2
public static int maximumValue2(String[] strs) {
//定义存储结果的变量
int res=0;
//内存循环中止时,外层循环continue
outter:
for (String str : strs) {
for (int i = 0; i < str.length(); i++) {
//当字符串中的某个元素为字母,直接获取长度
if(str.charAt(i)>='a'&&str.charAt(i)<='z'){
res=res>str.length()?res:str.length();
continue outter;//此时内层循环结束,外层循环跳出本次循环,执行下一次
}
}
//更新res值
res=res>Integer.parseInt(str)?res:Integer.parseInt(str);
}
return res;
}
题目描述:给你一个数组 nums
和一个值 val
,你需要移除所有数值等于 val
的元素,并返回移除后数组的新长度。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
解:由题可知,不需要考虑新数组长度后的元素,因此需要将后续有效元素移动至数组有效长度前的位置。
方法1==>记录元素需要移动的次数,对于数组中不等于val的元素,需要先前移动,移动到等于val的元素所在位置,这个移动的量通过等于val值的个数确认,比如在该元素前有3个这样的值,下标就需要减3
如上图所示,3需要移动到第一个2的位置,下标需要减2,以此类推
方法 2==>通过快慢指针标记不等于val的元素的下标与等于val的元素下标,对于不等于val的元素,将快指针对应元素赋值给慢指针所对应的元素
//方法1
public static int removeElement1(int[] nums, int val) {//{0,1,2,2,3,0,4,2}
//定义需要返回的新数组的长度与等于val的元素的个数
int res=nums.length,changeIndex=0;
for (int i = 0; i < nums.length; i++) {
if(nums[i]==val){
//当有一个元素与val值相等,则新数组长度在原数组长度的基础上-1
res--;
//个数++,后续可以通过当前元素下标减去changeIndex得到要交换元素的所在下标
changeIndex++;
}else{
//当元素不等于val,交换
if(changeIndex>0){
nums[i-changeIndex]^=nums[i];
nums[i]^=nums[i-changeIndex];
nums[i-changeIndex]^=nums[i];
}
}
}
return res;
}
//方法2
public static int removeElement2(int[] nums, int val) {
//定义慢指针为k,循环中的i为快指针
int k=0;
for(int i=0;i
题目描述:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
解:题目可以分为这几种情况:
1.目标值在数组中存在====>返回该元素下标
2.目标元素在数组中不存在,但大于数组中下标为i的元素,并小于数组中下标为i+1的元素====>返回i+1
3.目标元素在数组中不存在,且大于数组的最后一个元素====>返回数组长度
public static int searchInsert(int[] nums, int target) {
for(int i=0;i等值
if(nums[i]==target){
return i;
}
try {
//情况2位于数组中
if(nums[i]target){
return i+1;
}
} catch (Exception e) {
//情况3 位于数组尾部
return nums.length;
}
}
return 0;
}
题目描述:给你两个字符串haystack和needle,请你在haystack字符串中找出needle字符串的第一个匹配项的下标(从0开始),如果 needle不是haystack的一部分,则返回-1。
解:设置快慢指针,由快指针遍历haystack字符串,慢指针遍历needle字符串,当快指针等于字符串长度,遍历结束,若此时慢指针还未到达needle字符串尾部,则说明needle不是haystack的一部分。在遍历过程中,判断快指针与慢指针指向的元素是否相同,若相同则同时++,遍历下一个元素,否则慢指针为0,从头开始遍历needle字符串,快指针回退k长度的下一个位置,直到遍历到结果或快指针等于字符串haystack长度。
public static int strStr(String haystack, String needle) {
//设置快慢指针,其中i为快指针,k为慢指针
int k=0,i=0;
while(i
题目描述:给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。
解:对于本题有两种方式解答;
方式1===>对数组进行排序,相同的元素一定在相邻的位置,此时只需要判断下标为i的元素与下标为i+1的元素是否相同,当相同时,返回true,否则返回false
方式2===>使用set集合存储元素,当元素无法存入set集合时,说明该元素已经出现过,返回true,否则返回false
//方式1
public static boolean containsDuplicate1(int[] nums) {
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {
if(nums[i]==nums[i+1]){
return true;
}
}
return false;
}
//方式2
public static boolean containsDuplicate2(int[] nums) {
HashSet set = new HashSet<>();
for (Integer num:nums) {
if(!set.add(num)){
return true;
}
}
return false;
}
题目描述:给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
解:使用hashMap集合,将元素与元素出现的次数以键值对的形式存储,并遍历该map集合,取出value为1的元素
public static int singleNumber2(int[] nums) {
HashMap map = new HashMap<>();
for (Integer num:nums) {
map.put(num,(map.get(num)!=null?map.get(num)+1:1));
}
System.out.println(map);
for (Integer key : map.keySet()) {
if(map.get(key).equals(1)){
return key;
}
}
return -1;
}
题目描述:给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
解:利用set集合,将数组中的元素存入集合中,当某个元素重复出现时,删除集合中的该元素,遍历结束,集合中的元素均只出现一次
public static int[] singleNumber3(int[] nums) {
HashSet set = new HashSet<>();
for (int num : nums) {
if(!set.add(num)){
//当无法添加进集合,删除该元素
set.remove(num);
}
}
//将集合转换为int数组返回
int[] res=new int[set.size()];
int index=0;
for (Integer item : set) {
res[index]=item;
index++;
}
return res;
}
题目描述:给你一个整数x,如果x是一个回文整数,返回 true;否则,返回 false.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
解:对于回文数,首先一定是一个正整数,其次,它中心对称,即最高位与最低位相同,这样依赖在不使用字符串的前提下,通过先获取该数字的个位,通过相乘累加的形式得到一个数字。
举个例子,对于数字2345,要想让它颠倒,这里个位的5就需要变成千位的5,而二者的关系仅能通过数字的位数达到,即让5*4次10,这个过程放到循环中其实是很容易实现的。
对于一个数字,我们每次获取到它的余数,并在后一次遍历时使用这个保存结果的数乘以进制的权次幂再加上本次获取的余数,那么当循环结束的时候,就可以得到颠倒的数字。
还是刚才的2345,对于个位,我们已经得到了,此时使用进制10的权次幂乘以结果数再加余数5即可得到5(对于第一次计算,结果数为0),该数除10,个位切换为4,并将结果保存。再一次遍历,此时个位为4,获取上一次的结果5乘以10的1次幂加上本次余数4即可得到54.....以此类推。
public static boolean isPalindrome(int x) {
int res=0;
if(x<0){
return false;
}
while(x!=0){
res=res*10+x%10;
x/=10;
}
return res==x;
}