leetcode(1)

两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路:

将数组所有元素与其下标构成散列表,词条就是数组中的元素,选一个词条,target减去该词条所得的结果,也是数组中的元素,即用结果词条去表中查询是否存在,因为需要创建哈希表,空间复杂度为O(n),时间复杂度:创建哈希表O(n),单次遍历O(n),总查询次数O(n),所以总时间复杂度为O(n)。

#include <vector>
#include <unordered_map>

using namespace std;

class Solution {
public:
	static vector<int> twoSum(vector<int>& nums, int target) {
		vector<int> rel;
		unordered_map<int, int> hashMap;
		for (int i = 0 ; i < nums.size(); ++i)
			hashMap[nums[i]] = i;

		for (int i = 0; i < nums.size(); ++i)
		{
			int r = target - nums[i];
			if (hashMap.count(r) > 0 && hashMap[r] != i)
			{
				rel.push_back(i);
				rel.push_back(hashMap[r]);
				return rel;
			}
		}
		return rel;
	}
};

 两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

 思路:

1.相加方法就是普通的两个多位数相加,只是题目把多位数以链表的形式给出,故需要引入链表的性质,返回值为链表头。

2.在进行相加时,首先对低位相加,需要记录进位符,以及进入下一个高位时的判空

3.设l1长度为m,l2长度为n,时间复杂度为O(max(m, n))

/**
 * 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) {
        int carry = 0;
        // 记录链表头,作为返回值
        ListNode* preHead = new ListNode(0);
        // 将临时指针指向链表头,方便对链表进行add操作,以及位置更新
        ListNode* p = preHead;
        // 当l1和l2都为空,以及carry进位符为0时,不会再有高位产生,退出循环
        while (l1 != NULL || l2 != NULL || carry != 0)
        {
            // l1或l2其中一个为空时,按值取0进行计算,相加结果需要加上进位符
            int sum = (l1 != NULL ? l1->val : 0) + (l2 != NULL ? l2->val : 0) + carry;
            // 当前位置相加时产生的进位
            carry = sum / 10;
            // 将当前位置的值作为结果,接到链表上作为链表下一个值
            p->next = new ListNode(sum % 10);
            // 更新计算位置
            p = p->next;
            l1 = l1 != NULL ? l1->next : l1;
            l2 = l2 != NULL ? l2->next : l2;
        }
        // 去掉链表头的0
        return preHead->next;
    }
};

无重复字符的最长子串

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

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是"b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
      请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。

思路:

1.使用map记录字符与其下标位置,方便查找,当遇到重复字符时,快速获取上一个重复字符的下标位置

2.提前先遍历字符串,初始化各个字符的其实下标为-1

3.取start指向当前无重复字符串的其实位置

4.当字符的当前下标位置在start之后时,说明该字符已包含在当前无重复字符串中,如果再次遇到该字符,说明无重复字符串结构被破坏

5.记录无重复字符串长度,从start一直到碰到重复字符的前一个下标位置

6.遍历完整个字符串,需要记录最后一段无重复字符串长度

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		if (s.empty())
			return 0;

		// 提前先遍历字符串,初始化各个字符的其实下标为-1
		map<char, int> rel;
		for (int i = 0; i < s.length(); ++i)
			rel[s[i]] = -1;

		int maxLen = 0;
		// 记录单词开始位置,重复时,指向该重复字符位置的下一个
		int start = 0;
		for (int i = 0; i < s.length(); ++i)
		{
			if (rel[s[i]] >= start)
			{
				int len = i - start;
				start = rel[s[i]] + 1;
				if (maxLen < len)
					maxLen = len;
			}
			rel[s[i]] = i;
		}

		// 记录扫描到末尾的最后一段长度,与maxLen比较
		int len = s.length() - start;

		if (maxLen < len)
			maxLen = len;

		return maxLen;
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值