标签:max 扩大 情况 映射 val key next range 链表
leetcode 1-3题题解,用C++和python实现
解题思路
暴力解法
嵌入两层循环:第一层:i 从 0 到 n-2 ; 第二层: j 从 i+1 到 n-1;判断nums[i] +nums[j] == target, 如果成立则是正确答案。时间复杂度O(n^2)
**map解法 O(n*logn)**
把数组存在一个map里边,map的key是数组的值,map的value是数组的下标,这样只需要遍历原数组,查看a = target - nums[i]的值在不在map的key中,如果存在,并且map[a]与i不相等,则这两个值就是需要返回的下标。
时间复杂度O(n),空间复杂度O(n)
代码如下:
C++
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> myset;
vector<int> results;
for(auto tmp = nums.begin(); tmp<nums.end(); tmp++)
myset[*tmp] = tmp - nums.begin();
for(auto tmp = nums.begin(); tmp<nums.end(); tmp++)
{
if(myset.find(target - *tmp) != myset.end() && (*myset.find(target - *tmp)).second != (tmp-nums.begin()))
{
results.push_back(tmp-nums.begin());
results.push_back(myset[target - *tmp]);
break;
}
}
return results;
}
};
python
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
map = {}
for i in range(len(nums)):
if map.__contains__(target - nums[i]):
return [map[target - nums[i]], i]
map[nums[i]] = i
解题思路
从左到右遍历链表,以此相加,每一个位置生成一个新的节点
时间复杂度:O(max(len(l1), len2(l2))
考虑边界
进位的处理:carry表示进位,当最后一位还有进位时,即使l1和l2均为NULL的情况下,还需要生成一个新的节点
代码如下:
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head = new ListNode(0); //建立观察节点
ListNode *temp = head;
int carry = 0; //保留进位
int sum = 0;
while(l1 || l2)
{
if(l1 && l2) //两个链表都非空
{
sum = l1->val + l2->val + carry;
l1 = l1->next;
l2 = l2->next;
}
else if(l1)
{
sum = l1->val + carry;
l1 = l1->next;
}
else
{
sum = l2->val + carry;
l2 = l2->next;
}
//求出和和进位 添加到新的链表
carry = sum/10;
sum = sum % 10;
head->next = new ListNode(sum);
head = head->next;
if((l1 == NULL || l2 == NULL) && carry == 0)
{
head->next = l1 ? l1 : l2; //将非空链表的剩余节点添加到新联表中
return temp->next;
}
}
if (carry) //如果最后以为还有进位
{
head->next = new ListNode(carry);
}
//head->next->next = NULL;
return temp->next;
}
};
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
p=result=ListNode (-1)
temp=0
while l1 and l2:#当l1和l2属于同长度部分
sum=l1.val+l2.val+temp
temp=int(sum/10)
ptemp=ListNode(sum%10)
p.next=ptemp
p=p.next
l1=l1.next
l2=l2.next
temp1=l1 or l2
while temp1:#当l1和l2属于不同长度部分
sum=temp1.val+temp
temp=int(sum/10)
ptemp=ListNode(sum%10)
p.next=ptemp
p=p.next
temp1=temp1.next
if temp:
p.next=ListNode(temp)
return result.next
如果给一个例子"abcabcbb",让你手动找无重复字符的子串,该怎么找?一个字符一个字符的遍历,比如a,b,c,然后又出现了一个a,那么此时就应该去掉第一次出现的a,然后继续往后,又出现了一个b,则应该去掉一次出现的b,以此类推,最终发现最长的长度为3。所以说,我们需要记录之前出现过的字符,记录的方式有很多,最常见的是统计字符出现的个数,但是这道题字符出现的位置很重要,所以我们可以使用HashMap来建立字符和其出现位置之间的映射。进一步考虑,由于字符会重复出现,到底是保存所有出现的位置呢,还是只记录一个位置?我们之前手动推导的方法实际上是维护了一个滑动窗口,窗口内的都是没有重复的字符,我们需要尽可能的扩大窗口的大小。由于窗口在不停向右滑动,所以我们只关心每个字符最后出现的位置,并建立映射。窗口的右边界就是当前遍历到的字符的位置,为了求出窗口的大小,我们需要一个变量left来指向滑动窗口的左边界,这样,如果当前遍历到的字符从未出现过,那么直接扩大右边界,如果之前出现过,那么就分两种情况,在或不在滑动窗口内,如果不在滑动窗口内,那么就没事,当前字符可以加进来,如果在的话,就需要先在滑动窗口内去掉这个已经出现过的字符了,去掉的方法并不需要将左边界left一位一位向右遍历查找,由于我们的HashMap已经保存了该重复字符最后出现的位置,所以直接移动left指针就可以了。我们维护一个结果res,每次用出现过的窗口大小来更新结果res,就可以得到最终结果了。
代码
C++
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> m(256,-1);
int res = 0, left = -1;
for(int i = 0; i < s.size(); ++i)
{
left = max(left, m[s[i]]);
m[s[i]] = i;
res = max(res, i - left);
}
return res;
}
};
python
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
res = 0
List = []
for i in s:
if i not in List:
List.append(i)
res = max(res, len(List))
else:
index = List.index(i)
List.append(i)
List = List[index+1:]
return res
标签:max 扩大 情况 映射 val key next range 链表
原文地址:https://www.cnblogs.com/chengdongliang/p/11949151.html