题目2.
2. 两数相加https://leetcode.cn/problems/add-two-numbers/
想法:从头节点开始,对应位置相加,注意保存进位,累加到下一个节点;注意每次连接新节点都要新创建节点,最高位若有进位需额外创建一个节点。
代码:
/**
* 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 res = new ListNode(); //只是一个节点,后续节点还需要创建
ListNode cur = res;
int carry = 0;
while(l1!=null||l2!=null){
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
int sum = x+y+carry;
carry = sum/10;
sum = sum%10;
cur.next = new ListNode(sum);
cur = cur.next;
if(l1 != null)
l1 = l1.next;
if(l2 != null)
l2 = l2.next;
}
if(carry > 0) {
cur.next = new ListNode(carry);
}
return res.next;
}
}
结果:
题目3:
3. 无重复字符的最长子串https://leetcode.cn/problems/longest-substring-without-repeating-characters/
想法:借助hashmap;遍历字符串,将字符存入hashmap;如果该字符已存在,则比较当前len和i-j的大小;若不存在,则直接len++。
代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> map = new HashMap<>();
int len=0,res=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(map.containsKey(c)){
int j=map.get(c);
len=len<(i-j)?len+1:i-j;
}
else
len++;
res=Math.max(res,len); //最大长度
map.put(c,i);
}
return res;
}
}
结果:
题目5:
5. 最长回文子串https://leetcode.cn/problems/longest-palindromic-substring/
想法:动态规划。如果bab是回文,那么cbabc也是回文;则需要一个数组记录子串是否回文,再寻找最长长度;因最终需要返回回文子串,注意记录回文子串的起始位置。
我们用一个 boolean dp[l][r] 表示字符串从 i 到 j 这段是否为回文。
试想如果 dp[l][r]=true,我们要判断 dp[l-1][r+1] 是否为回文,及在(l-1)和(r+1)两个位置是否为相同的字符,便会减少很多重复计算。
初始状态,l=r 时,此时 dp[l][r]=true。
状态转移方程,dp[l][r]=true 并且(l-1)和(r+1)两个位置为相同的字符,此时 dp[l-1][r+1]=true。
代码:
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if(len<2)
return s;
int start=0;
int max=1;//最长回文串的长度
boolean[][] dp = new boolean[len][len];//dp数组
for(int r=1;r<len;r++){
for(int l=0;l<len;l++){
if(s.charAt(r)==s.charAt(l) && (r-l<=2||dp[l+1][r-1]) ){
dp[l][r]=true;
if(r-l+1>max){
max=r-l+1;
start=l;
}
}
}
}
return s.substring(start,start+max);
}
}
结果:
题目11:
11. 盛最多水的容器https://leetcode.cn/problems/container-with-most-water/
想法:本题为计算索引差和短边形成的长方形面积最大值。使用双指针法。
在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 -1−1 变短:
若向内 移动短板 ,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 可能变大,因此下个水槽的面积可能增大 。
若向内 移动长板 ,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 不变或变小,因此下个水槽的面积 一定变小 。
因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。
代码:
class Solution {
public int maxArea(int[] height) {
int i=0,j=height.length-1;
int max=0,tmp=0;
while(i<j){
if(height[i]<height[j]){
tmp=height[i]*(j-i);
i++;
}
else{
tmp=height[j]*(j-i);
j--;
}
max=max>tmp?max:tmp;
}
return max;
}
}
结果:
题目15:
15. 三数之和https://leetcode.cn/problems/3sum/
想法:先排序,排序后从左端开始遍历,先得到a=nums[i],再在后面使用双指针法寻找bc之和为-nums[i],注意跳过重复元素。
代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2)
List<List<Integer>> res = new ArrayList<>();
if(nums.length<3)
return res;
Arrays.sort(nums);// O(nlogn) 排序
for(int i=0;i<nums.length-2;i++){// O(n^2)
if(nums[i]>0)// 第一个数大于 0,后面的数都比它大,肯定不成立了
break;
if(i>0 && nums[i]==nums[i-1])// 去掉重复情况
continue;
int target = -nums[i];// 定一个找两个,下面是双指针
int left=i+1,right=nums.length-1;
while(left<right){
if(nums[left]+nums[right]==target){
res.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
// 首先无论如何先要进行加减操作
left++;
right--;
while(left<right && nums[left]==nums[left-1])// 左边去重
left++;
while(left<right && nums[right]==nums[right+1])// 右边去重
right--;
}else if(nums[left]+nums[right]>target){
right--;
}else{ // nums[left]+nums[right]<target
left++;
}
}
}
return res;
}
}
结果: