1-两数之和
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
解题思路:
我们主要通过map的数据类型进行存储,主要是因为map能够直接根据key来直接获取value,这就使得我们后面获取数组下标的过程更加方便.
我们首先将数组的所有元素及其下标全部存储起来,这样我们循环的过程中就可以直接进行检测map中是否含有差值的key,如果有的话,那么我们就可以直接返回了.没有则继续循环检测.
但是在这个里面我们需要考虑一个特殊的情况就是如果出现一个数组元素刚好是target的半值时,那么很显然是会直接返回两次该数组元素的下标的,就比如说下面这种情况:
target=6,num[]={3,2,4}
那么很显然我们最后返回的结果就会是{0,0},所以我们需要单独将这种情况拎出来,这种就在我们一开始存储元素的时候就需要进行判断,并且只能 是先判断是否有该元素再put ,因为map如果出现同样的key的话是会直接覆盖掉的,所以我们必须先判断,在put.
就是下面我圈出来的部分:
源代码:
class Solution { public static int[] twoSum(int[] nums, int target) { int []num=new int[2]; Map<Integer, Integer>map=new HashMap<Integer, Integer>(); for(int i=0;i<nums.length;i++) { if(map.containsKey(nums[i])) { if(target%2==0&&target/2==nums[i]) { num[0]=map.get(nums[i]); num[1]=i; return num; } } map.put(nums[i],i); } for(int i=0;i<map.size();i++) { if(map.containsKey(nums[i])&&map.containsKey(target-nums[i])&&target/2!=nums[i]) { num[0]=map.get(nums[i]); num[1]=map.get(target-nums[i]); return num; } } return num; } }
2-两数相加
题目描述:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
解题思路:
这一题的本质就是实现一个字符串形式的加减法.这里我们将例子转换成下面的图,大家就能看懂了.
大致的思路有了之后就剩下一些细节方面的问题了
首先第一点的就是为了防止出现空指针异常,需要注意下面几点
l1或l2为null以后,再获取他们的val值就会出现空指针异常,需要进行判断
在l1节点以及l2节点后移的过程中最后会出现l1或l2的next节点已经为空的情况,如果继续执行l1=l1.next,就会出现空指针异常,需要进行判断
其次就是注意我们最会的循环结束条件,这里大家肯定能够想到的就是 l1!=null||l2!=null 意思就是只要有一个链表没有结束,那么逐位相加的过程就需要继续执行,这个是对的,但是我们还要注意一点就是有可能我们的位数已经结束了,但是还存在我们的最后一位逐位相加之后向前产生了进位,那么很显然我们还需要再给这个进位添加一位.就好比下面这个例子:
[1] ,[9,9]
那么很显然我们最后得到的结果应该是[0,0,1],显然我们最后的位数中还有一位就是我们最后的一个进位,所以我们的循环结束条件应该是while(l1!=null||l2!=null||flag)意思就是只要任意一个节点没有空,并且仍然有进位的话,那么我们就需要继续执行下面的操作.
源代码:
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { boolean flag=false; StringBuffer str1=new StringBuffer(); while(l1!=null||l2!=null||flag) { int result=0; //为了防止出现l1或l2出现null,出现空指针异常 if(l1==null&&l2!=null) result+=l2.val; else if(l1!=null&&l2==null) result+=l1.val; else if(l1!=null&&l2!=null) result=l1.val+l2.val; //通过flag来判断是否需要进位 if(flag) result+=1; str1.append(result%10); //判断当前的位数和是否需要向前进位 if(result>=10) flag=true; else flag=false; if(l1!=null&&l1.next!=null){ l1=l1.next; }else{ l1=null; } if(l2!=null&&l2.next!=null){ l2=l2.next; }else{ l2=null; } } //新建各个节点信息 ListNode []listNodes=new ListNode[str1.length()]; for(int i=0;i<listNodes.length;i++) { listNodes[i]=new ListNode(Integer.parseInt(""+str1.charAt(i))); } //将各节点串起来 for(int i=0;i<listNodes.length-1;i++) { listNodes[i].next=listNodes[i+1]; } return listNodes[0]; } }
3-无重复字符的最长子串
题目描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:
输入: s = “”
输出: 0
解题思路:
这里我们选择通过List的数据结构来解决该问题.
我们这次主要就是通过每次循环先判断List中是否已经有了该元素,如果已经有了该元素的话,那么就跳出该循环,没有的话,我们就添加元素到我们的List之中,并且同时进行长度的判断,只要长度是大于我们的定义的length,我们就将该List的长度赋给我们的length,那么之后我们就只需要返回该length即可.
源代码:
class Solution { public int lengthOfLongestSubstring(String s) { int length=0; for(int i=0;i<s.length();i++) { //新建一个空的List List<Character>list=new ArrayList<Character>(); for(int j=i;j<s.length();j++) { //判断是否已经有了重复的元素 if(list.contains(s.charAt(j))) // 如果有就跳出循环 break; //没有重复的元素 else { //添加该元素,同时判断长度大小 list.add(s.charAt(j)); if(list.size()>=length) length=list.size(); } } } return length; } }