题目1
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法1:暴力双重循环
这个解法很容易想到,而且实现起来十分简单,最多只需要进行(N,2)次数的比较即可,时间复杂度O(n2),具体实现如下所示。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result=new int[2];
for(int i=0;i for(int j=i+1;j if(nums[i]+nums[j]==target){ result[0]=i; result[1]=j; return result; } } } return result; } } 解法2:利用哈希表来判断 哈希表这种解法有使用条件,要求nums数组无重复项,否则就会出现多个重复的键被当作一个,方法是首先一次遍历,将所有数据输入到哈希表,然后第二次循环,来判断target-nums[i]是否在哈希表中存在。具体实现如下。 class Solution { public int[] twoSum(int[] nums, int target) { Map for (int i = 0; i < nums.length; i++) { map.put(nums[i], i); } for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement) && map.get(complement) != i) { return new int[] { i, map.get(complement) }; } } throw new IllegalArgumentException("No two sum solution"); } } 但是这种解法增加了空间,但是hashmap本身的containsKey方法就类似于一层循环,时间上并没有很大提升,只是编码效率会比暴力法稍有提升。 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/add-two-numbers 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 解法:所见即所得 这就是一个小学数学的加法,按照数学思维来写代码就可以了,这道题目我个人觉得主要是考察数据结构,链表的使用和尾插,我看这道题的评论上说,有人想到了将这两个链表先转化为数字,然后通过直接求和再转化为链表,看似简单可行,实际上如果链表足够长,Long Long也是存不下的,反而增加时间以及空间的复杂度。具体解法如下。 public ListNode addTwoNumbers(ListNode l1,ListNode l2){ ListNode root=new ListNode(0); ListNode cursor=root; int add=0; while (l1!=null||l2!=null||add!=0){ int a=l1.val; int b=l2.val; int sum=a+b+add; add=sum/10; ListNode node=new ListNode(sum%10); cursor.next=node; cursor=node; if (l1!=null) l1=l1.next; if (l2!=null) l2=l2.next; } return root.next; } 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3: 输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 解法: 这个是在评论里面找到的解法,果然都是大神级别,自愧不如,先上代码和我自己理解加的一部分解释。 public static int lengthOfLongestSubstring(String s){ //a b c a b c d a d e //0 1 2 3 4 5 6 7 8 9 int maxSize =0; //记录ASCII 码字符出现的位置,以字符作为下标 int[]dict =new int[128]; //为了方便理解,这里把数组内容全部设为 -1,之后在记录的时候就可以从 0 开始,方便理解 Arrays.fill(dict, -1); //用于记录重复 ASCII 码字符出现的位置的值 int repeatValue = -1; // 当前下标 int i =0; int ASCII; while (i < s.length()) { ASCII = s.charAt(i);//获取当前字符的ASCII码 //如果当前位置的值 > repeatValue,证明当前位置已经赋过一次值了,证明字符重复 //dict[ASCII]是当前字符的位置 if (dict[ASCII] > repeatValue) //更新 repeatValue 为之前赋值的下标 repeatValue =dict[ASCII]; //将当前下标赋值到数组相应位置 dict[ASCII] = i; //i - repeatValue(去除重复部分) // 比如 abcabcdade 中的三个 a 的计算abca - a(3 - 0)=bca abcabcda - abca(7 - 3)=bcda maxSize =Math.max(maxSize, i - repeatValue); //s.length() - repeatValue - 1 判断剩下的数有没有必要继续循环 //比如 abcabcdade 最后的 a(当 i = 7 repeatValue = 3) ,abcabcdade - abca(10-3-1) = bcdade 剩下最多有六位 //比如 abcabcdade 最后的 d(当 i = 8 repeatValue = 6) ,abcabcdade - abcabcd(10-6-1) = ade 剩下最多也是三位 if (maxSize >= s.length() - repeatValue -1) { return maxSize; } i++; } return maxSize; } 其实这个解法与滑动窗口类似,这里面的repeatValue就是相当于尾指针,都是在遇到重复字符后更新位置,每次循环都更新下最大长度,算法简洁,理解起来稍微有些困难,让我自己想怕是要几年。
题目2
题目3