2024年1月27日第三天编程训练,今天主要是进行一些题训练,包括简单题3道、中等题2道和困难题1道,昨天没有做完,自制力还是不行,我写这个的初衷只是为了记录自己每天干了什么,希望能坚持下去。
链接: 丑数
难度: 简单
题目:
运行示例:
思路:
由题目可知,这是一个映射关系,可以利用哈希表来做,但是只用一个哈希表无法完成双向绑定的效果故需要利用两个哈希表。
代码:
class Solution {
public:
bool wordPattern(string pattern, string s) {
unordered_map<char,string> map;
unordered_map<string,char> rmap;
vector<string> vtr;
int t =-1;
for(int i = 0 ; i < s.size(); i++){
if(s[i] == ' '){
t += 1;
vtr.push_back(s.substr(t,i-t));
t = i;
}
}
vtr.push_back(s.substr(t+1,s.size()-1));
int n = pattern.size();
int m = vtr.size();
if(m != n) return false;
for(int i = 0; i < n; i++){
map[pattern[i]] = vtr[i];
rmap[vtr[i]] = pattern[i];
}
for(int i = 0; i < n; i++){
if( map[pattern[i]] != vtr[i] || pattern[i] != rmap[vtr[i]]) return false;
}
return true;
}
};
思路:
数学问题,当自己面对4块石头时,无论怎样都无法胜出,故需避免总的石头数目为 4 的倍数。
代码:
class Solution {
public:
bool canWinNim(int n) {
return n%4 != 0;
}
};
思路:
这道题目如果单纯的用循环相加也能做,但是很有可能时间超过,所以我采用的是求前项和,要求指定区间内的和可以相减即可。
代码:
class NumArray {
public:
vector<int> sums;
NumArray(vector<int>& nums) {
sums.push_back(nums[0]);
for(int i = 1; i < nums.size(); i++){
sums.push_back(sums[i-1]+nums[i]);
}
}
int sumRange(int left, int right) {
if(left == 0) return sums[right];
return sums[right]-sums[left-1];
}
};
思路:
我是用递归做的,结果时间超过了。我看了解析是用动态规划做的,原因是当前字母的解码方法可以看做前面的解码方方法加上这个字母的解码方法。f[i]可以看作字符串 s的前 i个字符 s[1…i]s[1…i]s[1…i] 的解码方法数。
代码:
class Solution {
public:
int numDecodings(string s) {
int n = s.size();
vector<int> f(n+1);
f[0] = 1;
for(int i = 1; i <= n; i++){
if(s[i-1] != '0'){
f[i] += f[i-1];
}
if(i > 1 && s[i - 2] != '0' && ((s[i - 2] - '0') * 10 + (s[i - 1] - '0') <= 26) ){
f[i] += f[i-2];
}
}
return f[n];
}
};
链接: 反转链表
难度: 中等
题目:
运行示例:
思路:
一次遍历的话就用头插法进行实现,注意给的head是不带头指针的,所以为了方便起见可以创建一个带头指针的链表。
代码:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(left >= right) return head;
ListNode *dummyNode = new ListNode(-1);
dummyNode->next = head;
ListNode*p,*q,*curr;
p = dummyNode;
for(int i = 0; i < left-1; i++){
p = p->next;
}
curr = p->next;
for(int i = 0; i < right - left; i++){
q = curr->next;
curr->next = q->next;
q->next = p->next;
p->next = q;
}
return dummyNode->next;
}
};
运行示例:
思路:
对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中.我用的是哈希表的思路,但是空间复杂度不符合题意。我看了题解,他们用的是置换和搞一个标记。置换是指将出现过的的整数置换到数组的对应位置,大于n+1的直接舍弃。搞一个标记即对出现过的整数在数组对应位置上加一个负号,然后遍历第一个是正数的位置即为结果。
代码:
置换:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for(int i = 0; i < n; i++){
while(nums[i] > 0 && nums[i] <= n && nums[nums[i] -1 ] != nums[i]){
swap(nums[nums[i] - 1], nums[i]);
}
}
for(int i = 0; i < n; i++){
if(nums[i] != i+1){
return i + 1;
}
}
return n + 1;
}
};
标记
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for(int i = 0; i < n; i++){
if(nums[i] <= 0){
nums[i] = n + 1;
}
}
for(int i = 0; i < n; i++){
int num = abs(nums[i]);
if(num <= n){
nums[num - 1] = -abs(nums[num - 1]);
}
}
for(int i = 0; i < n; i++){
if(nums[i] > 0 ){
return i + 1;
}
}
return n + 1;
}
};