- 记录于2019年5月16日
1. 两数之和
① 题目描述
- 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
- 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
- 示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
② 暴力求解
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length - 1; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[]{
i,j};
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
③ 两次hashMap遍历
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
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");
}
2. 两数相加
① 题目描述
- 给出两个
非空
的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 - 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
- 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
- 示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
② 情况分析
③ 元素加法
- 总结所有的情况,首先要考虑carry,carry可能是最后一位的加法进位,导致链表长度变长。
- 针对有链表为null和链表长度不一致的情况,巧妙使用
||
运算符,只有当两个链表的都为null时,才停止加法计算。 - 使用好辅助的链表,一个指向初始node,一个用于指向当前node。
- 代码如下:
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode result = new ListNode(0);
ListNode p = l1, q = l2, curr = result;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = x + y + carry;
carry=sum/10;
curr.next=new ListNode(sum%10);
curr=curr.next;
if(p!=null){
p=p.next;
}
if(q!=null){
q=q.next;
}
}
if (carry!=0){
curr.next=new ListNode(carry);
}
return result.next;
}
3. 无重复字符的最长子串
① 题目描述
- 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
- 示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
- 示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
- 示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
② 暴力求解(Time Limit Exceeded)
public int lengthOfLongestSubstring(String s) {
if (s.length()==0){
return 0;
}
int max=1;
for (int i=0;i<s.length()-1;i++){
for (int j=i+1;j<s.length();j++){
if (helper(s,i,j)){
max=Math.max(max,j-i+1);
}else{
// 从start开始的串有重复字符,后面的不用再判断
break;
}
}
}
return max;
}
public boolean helper(String s, int start, int end) {
Set<Character> set = new HashSet<>(); // 利用set存储不重复的字符
for (int i = start; i <= end; i++) {
char ch=s.charAt(i);
if (set.contains(ch)){
return false;
}
set.add(ch);
}
return true;
}
③ 滑动窗口
- 对滑动窗口的介绍:
A sliding window is an abstract concept commonly used in array/string problems. A window is a range of elements in the array/string which usually defined by the start and end indices, i.e.
[i, j)
(left-closed, right-open). A sliding window is a window “slides” its two boundaries to the certain direction. For example, if we slide [i, j) to the right by 11 element, then it becomes[i+1, j+1)
(left-closed, right-open).
public int lengthOfLongestSubstring(String s) {
int len=s.length();
int i=0,j=0,max=0;
Set<Character> set=new HashSet<>();
while(i<len&&j<len){
if(!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
max=Math.max(max,j-i);// 每一步都要更新max
}else{
set.remove(s.charAt(i++));// 去除重复的字符从下一个位置开始查找不重复字符的子串
}
}
return max;
}