Leetcode 1:两数之和
题目描述
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
题目解析
直接看代码即可,非常清晰
代码实现
vector<int> twoSum(vector<int>& nums, int target) { vector<int>res(2,-1); map<int,int> tmp; for(int i=0;i<nums.size();i++) { if(tmp.count(target-nums[i])) { res[0]=tmp[target - nums[i]]; res[1]=i; break; } tmp[nums[i]]=i; } return res; }
复杂度
Leetcode 19:删除链表的倒数第N个节点
题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
代码实现
ListNode* removeNthFromEnd(ListNode* head, int n) { if (head == NULL ) return head; ListNode *dummy=new ListNode(-1); dummy->next = head; ListNode *pre = dummy; ListNode *end = dummy; //Move end to n+1 for (int i = 0; i < n + 1; i++) { end = end->next; } while (end != NULL) { pre = pre->next; end = end->next; } ListNode *dpoint = pre->next;//待删除的点 pre->next = dpoint->next; delete(dpoint); return dummy->next; }
复杂度
时间复杂度O(n)
Leetcode 70:爬楼梯
题目描述
题目解析
我们很容易就发现,由于我们可以走一步也可以走两步,那实际对于第n个台阶来说,其依赖于走第n-1阶有多少种方法(此时只需要再走1步即可)和走第n-2阶有多少种方法(此时只需要再走2步即可),也就是说f(n)=f(n-1)+f(n-2)
,为一个斐波那契数列。递归形式很简单,所以这里写了一个迭代形式。
代码实现
int climbStairs(int n) { if (n == 0 || n == 1) return 1; if (n == 2) return 2; int first = 1, second = 2; for (int i = 3; i <= n; i++) { int third = first + second; first = second; second = third; } return second;}
复杂度
时间复杂度:O(n),空间复杂度O(1)。
Leetcode 78:子集
题目描述
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。说明:解集不能包含重复的子集。
示例
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
代码实现
vector<vector<int>> subsets(vector<int>& nums) { vector<int> temp; vector<vector<int>> r; dfs(r, temp, nums, 0); return r; } void dfs(vector<vector<int>>& r, vector<int>& temp, const vector<int>& nums, int begin) { r.push_back(temp); for (int i = begin; i < nums.size(); i++) { temp.push_back(nums[i]); dfs(r, temp, nums, i + 1); temp.pop_back(); } }
实现消耗
Leetcode 79:单词搜索
题目描述
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例
board =[ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E']]
给定 word = “ABCCED”, 返回 true
.
给定 word = “SEE”, 返回 true
.
给定 word = “ABCB”, 返回 false
.
解题思路
看这个题,我们自己脑子里先有一个思路:首先遍历这个矩阵,寻找到第一个对应的字母,然后再对其上下左右方向进行搜索,寻找下一个字母。
我们还需要注意可能存在这样一种情况,比如说在矩阵中有两个A,其中第一个A的上下左右不符合我们的要求,而第二个A则符合。此时当我们遍历到第一个A的时候,符合要求,开始对它的上下左右搜索,结果搜索不到,此时不应该单纯返回false然后判断找不到,而是应该继续遍历这个矩阵,寻找第二个A。
所以这个题可以使用回溯法解决,涉及到了深度优先遍历和状态重置。
我们结合ABCCED
这个组合来顺一遍代码。
代码实现
vector<vector<int>>dir{ {-1,0},{1,0},{0,-1},{0,1} }; bool edfs(int x, int y, int ind, vector<vector<char>>& board, string& word, vector<vector<bool>>& visited){ //word长度为1的情况 if (ind == word.size() - 1) return word[ind] == board[x][y]; //其它情况 if (word[ind] == board[x][y]) { visited[x][y] = true;//找到了,在visited中相应坐标标记 //然后开始在上下左右寻找下一个字母 for (int i = 0; i < 4; i++) { int new_x = x + dir[i][0]; int new_y = y + dir[i][1]; if (new_x >= 0 && new_x < board.size() && new_y >= 0 && new_y < board[0].size() && !visited[new_x][new_y]) { if (edfs(new_x, new_y, ind + 1, board, word, visited)) return true; } } visited[x][y] = false; } //字符找不到 return false;}bool exist(vector<vector<char>>& board, string word) { int row = board.size(); int col = board[0].size(); vector<vector<bool>> visited(row, vector<bool>(col)); //从矩阵的第一个元素开始寻找与word第一个字母相对应的字母,若找不到,则j+1,j加到最后,就i+1,这样一行一行查找。 for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (edfs(i, j, 0, board, word, visited)) return true; } } //找不到就返回false return false;}