Leetcode解题笔记:题1~3

以下题目来自Leetcode,中文网站:https://leetcode-cn.com/

1-两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

1.暴力法

思路很简单,就是耗时长了点,不多说了

vector<int> twoSum1(vector<int>& nums, int target) {
		vector<int> ans;
		for (auto i = 0; i < nums.size(); i++)
			for (auto j = i + 1; j < nums.size(); j++)
				if (nums[i] + nums[j] == target) {
					ans.push_back(i);
					ans.push_back(j);
				}
		return ans;
	}
2.使用关联容器map

利用map高效查找的特性可以有效降低算法的时间复杂度
思路:

  • 想要找到满足 a[i]+a[j]=target 的i,j
  • 对每一个i, 以target-a[i]为key,i为value,构建map
  • 遍历数组,对每一个a[i],在map中进行查找,若找到一个key为a[i],那么答案也就出现了
vector<int> twoSum2(vector<int>& nums, int target) {
   	map<int, int> numsMap;
   	vector<int> ans;
   	for (auto i = 0; i < nums.size(); i++)
   		numsMap[nums[i]] = i;
   	for (auto j = 0; j < nums.size(); j++)
   	{
   		int v = target - nums[j];
   		if (numsMap.count(v) && numsMap[v] != j)
   		{
   			ans.push_back(j);
   			ans.push_back(numsMap[v]);
   			return ans;
   		}
   	}
   	return ans;
   }

注:利用map的下标查找会创建不存在的key的特性可以进一步改善代码,有时间我再写,5月6日更新,我写了,贴在下面。

vector<int> twoSum3(vector<int>& nums, int target) {
		map<int, int> nums_map;
		int i = 0;
		while (i < nums.size()) {
			if (nums_map.find(nums[i]) != nums_map.end())
				return { i,nums_map.find(nums[i])->second };
			nums_map[target-nums[i]] = i;
			i++;
			}
			return {};
}

2-两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

思路:

  • 链表对齐,构造一个进位数(没必要构造一个数组),相加、进位
  • 如果一个链表到头了,不妨置尾为0,不影响结果
  • 写得有点混乱,还得修改修改
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
   	int sum = 0, c = 0;
   	vector<int> ans;
   	while (1) {
   	    sum = (l1->val + l2->val + c) % 10;
   		c = (l1->val + l2->val + c) / 10;
   		ans.push_back(sum);
   		if (l1->next == NULL && l2->next == NULL) {
   			if (c == 1)ans.push_back(c);
   			break;
   		}
   		if (l1->next != NULL)
   			l1 = l1->next;
   		else
   			l1->val = 0;
   		if (l2->next != NULL)
   			l2 = l2->next;
   		else
   			l2->val = 0;
   	}
   	ListNode* head = new ListNode(0);
   	ListNode* temp = head;
   	for (auto i = 0; i < ans.size(); i++) {
   		ListNode* p = new ListNode(0);
   		p->val = ans[i];
   		temp->next = p;
   		temp = p;
   	}
   	return head->next;
   }

3-无重复字符的最长字串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

1.暴力法

思路:

  • 使用两个下标 i 和 j 表示待查找的最长字串的始末下标
  • 以 i 遍历 , 同时从 i 开始以 j 向末尾遍历,同时以一个 k 从 i 向 j 遍历,并记录 i j 之间的距离
  • 直到发现了一个s[k]==s[i],那么这一对(i,j)不是符合要求的,进入下一个i
int lengthOfLongestSubstring1(string s) {
   	int temp = 0;
   	int ans = 1;
   	if (s.size() != 0) {
   		for (int i = 0; i < s.size(); i++)
   			for (int j = i + 1; j < s.size(); j++) {
   				temp = j - i + 1;
   				for (int k = i; k < j; k++)
   					if (s[k] == s[j]) {
   						temp = 0;
   						break;
   					}
   				if (temp > ans) {
   					ans = temp;
   				}
   				if (temp == 0)break;
   			}
   		return ans;
   	}
   	else return 0;
   }
2.改进方法
  • 这个方法是在题目的评论区看见的,很快,也很简洁
  • 同样是3个参数i,j,k,减少遍历的层数可以有效减少耗时
int lengthOfLongestSubstring2(string s) {
			int  i = 0, j, k, max = 0;
			for (j = 0; j < s.size(); j++) {
				for (k = i; k < j; k++)
					if (s[k] == s[j]) {
						i = k + 1;
						break;
					}
				if (j - i + 1 > max)
					max = j - i + 1;
			}
			return max;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值