前言
提示:用前必看:
IT行业迅速发展,作为一个程序员,掌握算法更是必不可缺的技能,本文章将讲解Java版Leetcode从基础到加深算法以及思路,有的可能会有多种答题思路,包括暴力法和官方解答并附相关网址,欢迎小白提问,本文章讲持续更新中…。
一.两数之和(简单)
二.两数相加(中等)
三.无重复字符的最长子串(中等)
四.寻找两个正序数组的中位数(困难)
提示:以下是本篇文章正文内容,下面案例可供参考
1.两数之和(简单)
1.问题
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
https://leetcode.cn/problems/two-sum/
示例
示例 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]
2.解题思路
F1:正常思路(暴力破解):嵌套两层遍历,外层从下标为0开始,内从从1开始,当nums[i]+nums[j] == target 跳出循环,时间复杂度O(n2)
F2:官方思路:首先声明一个Map,key用来存这个数组的值,value来存数组的下表,当遍历数组的时候,如果map 包含key 为target - nums[i]的时候,说明找到了,如果不包含,把nums[i]存进map,即 map.put(nums[i], i);
继续下次循环,直到if成立,时间复杂度为O(n)
3.上代码
F1:
public int[] twoSum(int[] nums, int target) {
for (int k = 0; k < nums.length - 1; k++) {
for (int l = k+1; l < nums.length ; l++) {
if (nums[k] + nums[l] == target) {
return new int[]{k, l};
}
}
}
return new int[0];
}
F2:
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(target - nums[i])) {
//如果包含则代表找到了
return new int[]{map.get(target - nums[i]), i};
}
//注意 key存值,value存下标
map.put(nums[i], i);
}
return new int[0];
}
二.两数相加(中等)
1.问题
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
https://leetcode.cn/problems/add-two-numbers/
示例
示例 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]
2.解题思路
F1:官方思路:首先需要创建节点类,包含属性为:值,下一个节点两个属性,一个构造方法参数为val,准备工作做好后,然后编写方法,由题意可知,其实目的是两个链表同时进行,每个链表从0下标开始,相加,余数就是这个节点的值,如果超过10 是需要进位的,需要有变量存起来,在下次循环中加上这个值,最后在遍历完,如果进位值还有值(只可能是1或者0,0就不用管了),则新增一个next节点存该值,切记,每次node循环完,都需node=node.next ,来跳到下一个节点。
3.上代码
F1:
public class AddTwoNumbers {
public static void main(String[] args) {
ListNode listNode = new AddTwoNumbers().new ListNode(1);
listNode.next = new AddTwoNumbers().new ListNode(2);
listNode.next.next = new AddTwoNumbers().new ListNode(3);
ListNode listNode2 = new AddTwoNumbers().new ListNode(2);
listNode2.next = new AddTwoNumbers().new ListNode(9);
listNode2.next.next = new AddTwoNumbers().new ListNode(9);
ListNode resultNode = new AddTwoNumbers().new Solution().addTwoNumbers(listNode, listNode2);
while (resultNode != null){
System.out.print(resultNode.val);
resultNode = resultNode.next;
}
}
//leetcode submit region begin(Prohibit modification and deletion)
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 node1, ListNode node2) {
//res存放结果,cur为res的尾指针
ListNode res = new ListNode();
ListNode cur = res;
//表示进位
int carry = 0;
// 只要两个链表有一个不为空,就要继续
while (node1 != null || node2 != null){
//如果其中有一个到达结尾了,那么这个链表这一位的的数字就为0。
int a = node1 == null ? 0 : node1.val;
int b = node2 == null ? 0 : node2.val;
//两个链表的两位相加
int sum = a + b + carry;
//大于10进位 进位数是下次循环要被加起来的
carry = sum / 10;
//进位完剩下的余数,余数就是值
sum %= 10;
//创建一个节点接入res后面
cur.next = new ListNode(sum);
cur = cur.next;
//分别后移
if (node1 != null) node1 = node1.next; // 跳到下一个节点
if (node2 != null) node2 = node2.next; // 跳到下一个节点
}
//如果最后还有进位的话,增加一个节点(比如三位数相加高位超过10变成四位,第四位必为1)
if (carry == 1) cur.next = new ListNode(1);
return res.next;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}
三.无重复字符的最长子串(中等)
1.问题
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
https://leetcode.cn/problems/longest-substring-without-repeating-characters/
示例
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串
2.解题思路
F1:官方思路:其实这个跟两数之和有共通之处,都是借用了map的key存值,value存下标,由题意知,是要一个无重复字符串的最长字符数,比如abba,当碰到第二个b的时候就是说明遇到重复了,所以我们需要定义两个变量,max代表最大值,left代表用来滑动窗口,当遇到第二个b的时候,left就要变成b+1那个位置,max也是取最大值,
3.上代码
F1:
public class LongestSubstringWithoutRepeatingCharacters {
public static void main(String[] args) {
Solution solution = new LongestSubstringWithoutRepeatingCharacters().new Solution();
System.out.println( solution.lengthOfLongestSubstring("abba"));;
}
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
//abcbcbb
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
int max = 0; //用来存返回的最长无重复子串的数字
int left = 0; //用来滑动窗口
Map<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i))+1);
}
map.put(s.charAt(i),i);
max = Math.max(i-left+1,max);
}
return max;
}
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
int max = 0; //用来存返回的最长无重复子串的数字
int left = 0; //用来滑动窗口
Map<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if(map.containsKey(s.charAt(i))){
//map.get(s.charAt(i)) get key会拿到第二个b的定位,+1 是要left变成b的后一个位置
left = Math.max(left,map.get(s.charAt(i))+1);
}
//key存值,value存下标
map.put(s.charAt(i),i);
// max取最大值,是之前的max大还是新的循环i-keft+1大
max = Math.max(i-left+1,max);
}
return max;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}
四.寻找两个正序数组的中位数(困难)
1.问题
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n))
来源:https://leetcode.cn/problems/median-of-two-sorted-arrays/
示例
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
2.解题思路
F1:个人思路: 将两个数组合并并排序,根据中位数算法,奇数取一,偶数取2个/2,进行计算即可。
3.上代码
int[] newArray = IntStream.concat(IntStream.of(nums1), IntStream.of(nums2)).sorted().toArray();
if (newArray.length % 2 == 0) {
return ((double) newArray[newArray.length / 2 - 1] + newArray[newArray.length / 2]) / 2;
} else {
return newArray[newArray.length / 2];
}
总结
提示:持续更新中!!!
有惊喜哟~
关注公众号,随时学习最新内容,并与博主零距离交流!
持续更新中。。。