LeetCode
前言:知道的越多,不知道的就越多。
持续学习
始于:2021/08/05
gitee地址:gitee
开始慢慢补齐自己的短板-算法。
1、两数之和
题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 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 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一种:暴力解法
思路:
暴力解法比较容易想到。
利用两个循环进行遍历每个元素,外层循环锁定第一个元素,内层循环锁定第二个元素,然后这两个元素去判断之和是不是为目标数,是就返回对应的下标,不是的话就返回就继续循环。
代码:
public int[] twoSum(int[] nums, int target) {
int [] index =new int[2];
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
index[0]=i;
index[1]=j;
return index;
}
}
}
return index;
}
第二种:利用Hash表解题
思路:
利用Hash表来解题,将数组放在Hash表中,将值作为key,数组对应下标对应value,用目标数去减第一个数,得到一个剩下得值,然后利用这个值去判断是否存在Hash表中,以此循环。
代码:
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < nums.length; ++i) {
int num = target - nums[i];
/*判断hash表中是否存在这个key值*/
if (map.containsKey(num)) {
return new int[]{map.get(num),i};
}
/*将数组的值和下标添加到hash表*/
map.put(nums[i], i);
}
return null;
}
2、两数相加
date:2021/08/06
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 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]提示:
每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
迭代法
思路:
2+5=7 将7放在和链表对应的位置
4+6=10 因为一个节点只可以存一个数,故将个位放在和链表对应的位置,然后十位的1,进到下一个节点
3+4=7+1 =8 因为上一个节点有进位,还得加上进位的1才可以,然后将8放在和链表对应的位置。
我们可以把整个过程抽象成一个公式:
total=val1+val2+carry total 为总和,carry为进位
保存在和链表的值:val3=total%10
下一个节点的进位carry=total/10
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int next1 = 0;//进位
int total = 0;//总和
ListNode sum = new ListNode();//和链表
ListNode cur = sum;//加一个头指针
while (l1 != null && l2 != null) {//两个链表对其的时候
total = l1.val + l2.val + next1;
cur.next = new ListNode(total % 10);//写入和链表的个位
next1 = total / 10;//保存进位
l1 = l1.next;//向下移动
l2 = l2.next;
cur = cur.next;
}
while (l1 != null) {//l2为空了
total = l1.val + next1;
cur.next = new ListNode(total % 10);
next1 = total / 10;
l1 = l1.next;
cur = cur.next;
}
while (l2 != null) {
total = l2.val + next1;
cur.next = new ListNode(total % 10);
next1 = total / 10;
l2 = l2.next;
cur = cur.next;
}
if (next1 != 0) {
cur.next = new ListNode(next1);
}
return sum.next;
}
}
}
3、无重复字符的最长子串
date:2021/08/11
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:输入: s = “”
输出: 0提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力遍历解法
date:2021/08/12
思路:先将字符串转化为数组,用两个指针循环遍历数组,先将外层的字符放入hash表中。然后比较元素是否存在于hash表中,如何没有就就加入到哈希表,如何存在了就跳出内层循环,进行下一次外层循环。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AcIboS9h-1628767885284)(LeetCode.assets/image-20210812182412253.png)]
hashMap //定义一个散列表
for(i){
//将第一个元素放进hash表
for(j){
判断第j个元素是否在哈希表中
如果不在就放进hash表
if(hashMap.containsKey()){
}else{
如果存在哈希表中,那么我们就需要进行下一次寻找
那这一次内循环就结束
break;
}
}
}
public int lengthOfLongestSubstring(String s) {
char[] chars = s.toCharArray();
int maxLen=0;//记录最大长度
Map child = new HashMap();//将子串放入哈希集合
if (chars.length!=0){
maxLen=1;
}
for(int i=0;i<chars.length;++i){
//每次循环将set置空
child.clear();
//将i位置的元素放入
child.put(chars[i],i);
for(int j=i+1;j<chars.length;++j){
//判断子串中是否存在该元素
if(!child.containsKey(chars[j])){//如果不存在
//放入哈希表
child.put(chars[j],j);
}else {
break;
}
if (child.size()>maxLen){//哈希表长度大于最长
int len=child.size();
maxLen=len;
}
}
}
return maxLen;
}
滑动窗口解法
这道题主要用到思路是:滑动窗口
什么是滑动窗口?
其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!
一直维持这样的队列,找出队列出现最长的长度时候,求出解!
public int lengthOfLongestSubstring1(String s) {
char[] chars = s.toCharArray();
Map<Character,Integer> child = new HashMap();//将子串放入哈希集合
int maxLen=0;//记录最大长度
int front=0;//前指针
int next=1;//后指针
int value=0;//记录元素位置
if(chars.length!=0){
child.put(chars[front],front);
maxLen=1;
}
while(next<chars.length){
if(child.containsKey(chars[next])){//如果相等
child.remove(chars[value++]);//移除元素
front=value+1;//从这里开始循环b
// next=front+1;
// value++;
}else {//没有相同就放进去
child.put(chars[next],next);
next++;//数组下标下移
}
if(child.size()>maxLen){
maxLen=child.size();
}
}
return maxLen;
}