目录
1.给定target,找出数组里和为target的数组下标
题目描述:
平台提交代码:
测试结果:
思路:
用HashMap表
num数组里面的元素当作Key,方便到时候查找HasjMap里面是否含有这个Key(元素)。
下标当作Value,到时候可以用对应的元素(Key)去查找到下标(Value)
定义一个数组用来存放那两个和为target的元素的下标值
1.从num[0]开始
2.存储:把num[0]存入HashMap,Key是元素,Value是下标
3.查找:计算target-num[1]的值,看看这个值在HashMap里是否存在,用containskey方法 4.存储:存储num[1]
5.如果有,那么把num[1]以及target-num[1]对应的数组元素对应的下标存入自己定义的容量为2的数组,
可以用get方法,通过对应的Key去得到对应的Value(下标)6.查找:计算targer-num[2]的值,用containskey方法去查找是否存在这个值,
7.存储:如果不包含,那么就继续保存下一个(num[2])到HashMap
8如果有,那么把num[1]以及target-num[1]对应的数组元素对应的下标存入自己定义的容量为2的数组,
可以用get方法,通过对应的Key去得到对应的Value(下标)
9.如果不包含,那么就继续保存下一个(num[2])到HashMap
总之,num[0]只用存储,数组里的数除了num[0]以外的数,进行存储后就计算target-这个数的操作,去在哈希表里面进行查找、
是否存在target-这个数
没有的话就一直进行存储和查找,直到查找到可以和自己加起来的值为target为止
具体代码:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class solution {
public int[] twoSum(int[]nums, int target){
int []ret=new int[2];//用来存放下标的数组
int len=nums.length;
Map<Integer,Integer> hashmap=new HashMap<>();//用来存放整数数组里面的元素及其下标,元素为Key,下标为Value
hashmap.put(nums[0],0);//先把num[0]存进哈希表
for(int i=1;i<len;i++){
//从下标为1的数组元素开始进行存储再查找的操作
//一.查找
//1.算出target-num[i]的值
int differ=target-nums[i];
//2.查找哈希表中是否存在这个值,我们把数组里的元素当作了key可用contanisKey的方法查找
if(hashmap.containsKey(differ)){
ret[0]=hashmap.get(differ);//用key值获取下标
ret[1]=i;
}
//二.存储
hashmap.put(nums[i],i);
}
return ret;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//输入数组
String str=sc.nextLine().toString();//输入数组的内容,可以读取一整行,包括空格
str=str.replaceFirst("\\[","");
str=str.replaceFirst("\\]","");
String arr[]=str.split(",");//拆分字符串成字符串数组
int []aw=new int [arr.length];//定义一个长度和arr数组相同的int型的数组
for(int i=0;i<aw.length;i++){
aw[i]=Integer.parseInt(arr[i]);//将arr的内容复制到aw中
}
//输入target
int target=sc.nextInt();
//创建对象调用方法
solution s1=new solution();
System.out.println(s1.twoSum(aw,target));
}
}
注意:
- 在运行的时候,如果数组是[3,3]这类具有重复元素的数组,那么我们输出的下标应该是先出现的下标和后出现的下标进行输出,([0,1])而不是输出两个一模一样的下标 ([1,1]),所以在这里应该注意要先进行查找再进行存储。因为当数组里面有相同元素存在时,元素作为Key,那么在第二次进行存储的时候,后面的value会覆盖掉前面的value。
- String字符串可以调用replace方法删除字符
去掉 [ 这个符号时,记得加上转义字符\\
2.回文数
题目描述:
方法一:暴力法
呜呜呜呜,暴力法太难了,即麻烦,而且时间和空间复杂度都会很大
public class huiwen {
public boolean isPalindrome(int x) {
if(x<0)
return false;
boolean bool=true;
String str=String.valueOf(x);//将int型的x转换成了String类型
int length=str.length();
char[] num1=new char[length];//创建一个char类型的数组用来存储字符串正序的各位数字
char[] num2=new char[length];//创建一个数组用来存储字符串逆序的各位数字
for(int i=0;i<length;i++){
num1[i]=str.charAt(i);
}//存储正序数字
for(int i=length;i>0;i--){
System.out.println(num2[length-i]=str.charAt(i-1));//从0到length-1
}//存储逆序数字
for(int i=0;i<length;i++){
if(num1[i]!=num2[i]) {
bool = false;
break;
}
}//比较两个字符数组的元素是否一样,若出现了一个不一样,那么就令bool为FALSE,并跳出循环
return bool;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
huiwen h=new huiwen();
System.out.println(h.isPalindrome(num));
}
}
思路:
- 如果是负数那么必定不是回文数,返回false,如果是正数那么继续进行判断
- 首先把int数据转为String类型的数据
- 创建两个char类型的数组,char1和char2分别用来存储转换为String后的字符串的正序和逆序的字符 (用charAt()方法来获取String里面的单个字符)
- 然后用for循环来对两个char类型的数组进行比较,如果出现不同的,那么就令boolean bool的值为false,并跳出循环
- 返回定义的boolean类型数据
测试结果
方法二:
思路:
1.考虑特殊情况:
负数不可能是回文数,正数的个位数为0的数也不可能为回文数,一个数的开头不可能为0。所以负数以及个位数为0的正数在方法里面返回false
2.我们一般会采取将数字反转过来,再比较两个数是否相等,但是这里会存在数据溢出的风险,当一个数为2472748282919时没有溢出,但是反转过来时数据发生了溢出,这样不可行。我们可以观察到回文数都是对称的数字(奇数位数的数字关于中间的那个数字对称,偶数位数的数字关于中间的一条虚线对称),这时候,我们可以选择只取数字的前一半和后一半,然后把后一半数字反转过来与前一半数字进行比较。
3.在这里我们分两种情况对int x进行取半操作(reverted表示后半部分的数字反转过来)
在正在进行取半操作时,前半部分的数总大于后半部分的数,那什么时候停止呢?
运行到前半部分数等于(这种情况必是偶数位数)或者小于(可以是奇数位数的数字,也可以是偶数位数的数字)后半部分数反转过来的时候停止。
具体看下面分析
后半部分反转过来的数字一点点增大,一开始是小于前半部分的,直到后半部分反转过来的数等于或者大于前半部分,说明,没必要再进行取半这个操作了。
奇数位数的数字:把后半部分反转的数去掉末尾的数字与前半部分比较(因为后半部分的个位数存储了x这个数最中间的数字)
偶数位数的数字:直接后半部分反转过来的数与前半部分比较
具体代码
class Solution {
public boolean isPalindrome(int x) {
if (x < 0 || (x % 10 == 0 && x > 0)) {
return false;
}
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
return x == revertedNumber || x == revertedNumber / 10;
}
}
测试结果