leetcode前50题-java版
(1) 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
思路:首先这不是一个有序数组,不能通过一个双指针,left指向数组头,right指向数组尾。但是通过hashmap,key为元素值,value为元素下标,空间换取时间方法。
import java.util.*;
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
for(int i=0; i<nums.length; i++){
hashMap.put(nums[i], i);
}
for(int i=0; i<nums.length; i++){
if(hashMap.containsKey(nums[i])){
if(hashMap.containsKey(target-nums[i])){
if(i != hashMap.get(target-nums[i]))
return new int []{
i, hashMap.get(target-nums[i])};
} else {
hashMap.remove(nums[i]);
}
}
}
return new int[2];
}
}
(2) 两数相加
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储 一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
思路:没啥好说的,就是链表操作,虚拟头节点方法。
/**
* 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) {
ListNode p1=l1;
ListNode p2=l2;
ListNode root = new ListNode(0); // 虚拟头节点
ListNode p3=root;
int cur=0; // 表示进位值
int temp=0; // 表示当前位置应该为几
while(p1!=null && p2!=null){
temp = p1.val + p2.val + cur;
cur = temp/10;
temp = temp%10;
p3.next = new ListNode(temp);
p3=p3.next;
p1=p1.next;
p2=p2.next;
}
while(p1!=null){
temp = p1.val + cur;
cur = temp/10;
temp = temp%10;
p3.next = new ListNode(temp);
p3=p3.next;
p1=p1.next;
}
while(p2!=null){
temp = p2.val + cur;
cur = temp/10;
temp = temp%10;
p3.next = new ListNode(temp);
p3=p3.next;
p2=p2.next;
}
if(cur!=0) // 要考虑上面的最后一次操作中是否有进位
p3.next = new ListNode(cur);
return root.next;
}
}
(3)无重复字符的最长字串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcbacbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
思路:首先看到字符串,并且是和子串相关的,优先考虑双指针的滑动窗口。但是单纯的双指针怎么判断新遍历到的字符有没有在窗口范围内重复呢?而且单纯的双指针其时间复杂度为O(n^2)。所以通过hashmap,key为元素值,value为元素下标,空间换取时间,双指针中的end端访问一个新字符有没有在窗口范围内出现时就可以通过判断字符有没有在hahmap中的Key出现就可,避免了去遍历窗口范围内的所有字符;而且如果新字符在窗口内不存在就添加进hahmap,存在的话只能说明这个新字符在从下标 0 到 end 这段距离中出现过,是在 0 - start 还是 start - end范围内出现的不清楚,前者不影响我们的 start,后者需要更新 start,不管是前者还是后者都是需要把这个字符的下标进行更新的。整体时间复杂度相当于一次遍历。
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
HashMap<Character, Integer> map = new HashMap<>();
for(int start=0, end=0; end<n; end++){
char c = s.charAt(end);
if(map.containsKey(c)){
start = Math.max(start, map.get(c) + 1);
}
ans = Math.max(ans, end - start + 1);
map.put(c, end);
}
return ans;
}
}
(4)寻找两个正序数组的中位数
(5)最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
思路:简单粗暴的思路就是dp数组,求子串问题,一般都是双指针。画一个二维的方格图,分析下遍历dp数组时的顺序即可。
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
if(n==0) return "";
if(n==1) return s;
int [][] dp = new int [n][n]; //默认就是0
for(int i=0; i<n; i++){
dp[i][i] = 1;
}
int max=1;
String str=s.substring(0, 1);
for(int i=n-1; i>=0; i--){
for(int j=i+1; j<n; j++){
if(s.charAt(i)!=s.charAt(j)){
dp[i][j] = 0;
} else {
if(dp[i+1][j-1]>