LeetCode刷题(2021.8.5)
最近为了将来找工作做准备,所以准备刷刷leetcode上的算法题目,为了边刷题便总结以及将来能够更加方便的回顾,于是做了笔记,不做任何商业用途,如有侵权,请联系删除!
一.两数之和
1.问题描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。(来源:LeetCode链接:https://leetcode-cn.com/problems/two-sum)
2.解题思路
(1)暴力解题
什么是暴力解题,就是遇到链式的东西,直接从头到尾进行循环并判断,如果满足判断条件,跳出循环,否则继续循环。这种方法的坏处就是时间效率太低。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
for(int i = 0; i < nums.size(); i++)
{
for(int j = i + 1; j < nums.size(); j++)
{
if(nums[i] + nums[j] == target)
{
result.push_back(i);
result.push_back(j);
break;
}
}
}
return result;
}
};
(2)哈希表方法
在做算法题目的时候,如果碰到数组、字符串等的操作有时候把下标或者值作为哈希表的key或者value,能够有效降低在暴力解题法基础上的时间消耗。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> result;
unordered_map<int,int> map1;
for(int i = 0; i < nums.size(); i++)
{
auto it = map1.find(target - nums[i]);
if(it != map1.end())
{
result.push_back(it->second);
result.push_back(i);
break;
}
map1[nums[i]] = i;
}
return result;
}
};
**注:**哈希表的find函数查找的是键的位置。
二.两数相加
1.问题描述
给你两个非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序的方式存储的,并且每个节点只能存储 一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。(来源:LeetCode 链接:https://leetcode-cn.com/problems/add-two-numbers)
2.解题思路
这道题中规中矩,没什么难点,唯一要注意的是进位问题。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* currentNode1 = l1;
ListNode* currentNode2 = l2;
ListNode* result = new ListNode;
ListNode* movePtr = result;
int enterFlag = 0;
while(currentNode1 != NULL || currentNode2 != NULL)
{
ListNode resCurNode = {0};
int temp;
if(currentNode1 == NULL)
{
temp = currentNode2->val + enterFlag;
if(temp >= 10)
{
resCurNode.val = temp - 10;
enterFlag = 1;
}
else
{
resCurNode.val = temp;
enterFlag = 0;
}
currentNode2 = currentNode2->next;
}
else if(currentNode2 == NULL)
{
temp = currentNode1->val + enterFlag;
if(temp >= 10)
{
resCurNode.val = temp - 10;
enterFlag = 1;
}
else
{
resCurNode.val = temp;
enterFlag = 0;
}
currentNode1 = currentNode1->next;
}
else
{
temp = currentNode1->val + currentNode2->val + enterFlag;
if(temp >= 10)
{
resCurNode.val = temp - 10;
enterFlag = 1;
}
else
{
resCurNode.val = temp;
enterFlag = 0;
}
currentNode1 = currentNode1->next;
currentNode2 = currentNode2->next;
}
movePtr->val = resCurNode.val;
ListNode* newNode = new ListNode;
movePtr->next = newNode;
movePtr = newNode;
}
if(enterFlag == 1)
{
movePtr->val = 1;
movePtr->next = NULL;
}
else
{
ListNode* moveNode = result;
while(moveNode->next != movePtr)
{
moveNode = moveNode->next;
}
moveNode->next = NULL;
delete movePtr;
}
return result;
}
};
三.求最长无重复字符的子串长度
1.问题描述
给定一个字符串s ,请你找出其中不含有重复字符的最长子串 的长度。
2.解题思路
遇到这道题,脑海里的第一个想法就是暴力解题,用每个字符在字符串中进行比较,如果碰到重复的,取它走过的长度,标定为当前最长的字串长度。当然存在很多问题,没有解决,最后参考了别人的滑动窗口的算法。
依次放入字符串的每个字符到一个新的字符串中(滑动窗口),来判断新的字符串中是否含有重复的字符,如果有,滑动窗口左端移动到字符串重复位置的下一个位置,重复此操作。如例题中的 abcabcbb,新字符串 abc 满足题目要求,当窗口向后移动后a进入新字符串,新字符串变成了 abca,这时候不满足要求。所以,我们要移动窗口的左端,让它的左端移动到第一个a的后面,也就是b的位置上,这时候新的字符串变为bca。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int maxLen = 0;
int start = 0;
int end = 0;
int i = 0;
if(s.length() == 1) maxLen = 1;
while( start < s.length() && end < s.length() )
{
for(i = start; i < end; i++)
{
if(s[i] == s[end])
{
start = i + 1;
break;
}
}
maxLen = maxLen < (end - start + 1) ? (end - start + 1) : maxLen;
end++;
}
return maxLen;
}
};