移除元素
描述
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
你不需要考虑数组中超出新长度后面的元素。
题解:双指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int slow{0};
for(int fast=0;fast<len;++fast){
if(nums[fast]!=val)
nums[slow++]=nums[fast];
}
return slow;
}
};
题解:暴力
双层循环即可
反转字符串
描述
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]
题解
class Solution {
public:
void swap(char&c1,char&c2){
char tmp = c1;
c1=c2;
c2=tmp;
}
void reverseString(vector<char>& s) {
size_t left = 0,right = s.size()-1;
while(left <right){
swap(s[left],s[right]);
++left;--right;
}
}
};
替换数字
描述
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anumberbnumbercnumber”。
对于输入字符串 “a5b”,函数应该将其转换为 “anumberb”
输入:一个字符串 s,s 仅包含小写字母和数字字符。
输出:打印一个新的字符串,其中每个数字字符都被替换为了number
样例输入:a1b2c3
样例输出:anumberbnumbercnumber
数据范围:1 <= s.length < 10000。
题解
#include <iostream>
#include <string>
using namespace std;
void change_string(string&s){
size_t old_len = s.size();
int count{0};
for(int i=0;i<old_len;++i){
if(s[i]<='9'&&s[i]>='0')
++count;
}
s.resize(old_len+5*count);
size_t new_len = s.size();
for(int front = old_len-1,back=new_len-1;front>=0;--back,--front){
if(s[front]>='0'&&s[front]<='9'){
s[back]='r';
s[back-1]='e';
s[back-2]='b';
s[back-3]='m';
s[back-4]='u';
s[back-5]='n';
back-=5;
}else
s[back]=s[front];
}
}
int main(){
string s;
cin>>s;
change_string(s);
cout<<s<<"\n";
return 0;
}
翻转字符串里的单词
描述
示例 1:
输入: “the sky is blue”
输出: “blue is sky the”
示例 2:
输入: " hello world! "
输出: “world! hello”
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: “a good example”
输出: “example good a”
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
题解
class Solution {
public:
void deleteExtSpace(string&s){
int slow{0},fast{0};
size_t len{s.size()};
while(fast<len&&s[fast]==' ')
++fast;
while(fast<len){
if(fast>0&&s[fast]==' '&&s[fast-1]==' '){
++fast;continue;
}else{
s[slow++]=s[fast++];
}
}
if(slow-1>0&&s[slow-1]==' '){
s.resize(slow-1);
}else
s.resize(slow);
}
void reverseStr(string&s,int beg,int end){
if(end<beg)return;
while(beg<end){
char tmp = s[beg];
s[beg]=s[end];
s[end]=tmp;
++beg;
--end;
}
}
string reverseWords(string&s){
deleteExtSpace(s);
reverseStr(s,0,s.size()-1);
int i,j;
for(i=0,j=0;i<s.size();++i){
if(s[i]==' '){
reverseStr(s,j,i-1);
j=i+1;
}
}
reverseStr(s,j,i-1);
return s;
}
};
反转链表
class Solution {
public:
ListNode *reverseList(ListNode *head) {
if(!(head&&head->next))return head;
ListNode*pre = nullptr,*cur=head;
while(cur){
ListNode*tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
删除链表的倒数第N个节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode*fhead = new ListNode(0,head);
ListNode*slow = fhead,*fast = fhead;
while(n--)
fast = fast->next;
while(fast->next){
slow=slow->next;
fast=fast->next;
}
slow->next = slow->next->next;
return fhead->next;
}
};
链表相交
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
size_t lA{0},lB{0};
ListNode*a = headA;
while (a){
lA++;
a=a->next;
}
ListNode*b = headB;
while (b){
lB++;
b=b->next;
}
//a 短 b长
a=lA>lB?headB:headA;
b=lA>lB?headA:headB;
size_t len = lA>lB?lA-lB:lB-lA;
while (len--)
b=b->next;
while (a&&b){
if(a==b)
return a;
a=a->next;
b=b->next;
}
return nullptr;
}
};
环形链表II
class Solution {
public:
ListNode* detectCycle(ListNode *head) {
ListNode*slow=head,*fast=head;
while (fast && fast->next){
slow=slow->next;
fast=fast->next->next;
if(slow==fast){
//存在环
slow = head;
while (slow!=fast){
fast=fast->next;
slow=slow->next;
}
return slow;
}
}
return nullptr;
}
};
三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int> &nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
size_t len = nums.size();
for (int i = 0; i < len; ++i) {
if (nums[i] > 0)break;
//去重i
if (i > 0 && nums[i] == nums[i - 1])continue;
int slow = i + 1, fast = len - 1;
while (slow < fast) {
if (nums[i] + nums[slow] + nums[fast] > 0)
--fast;
else if (nums[i] + nums[slow] + nums[fast] < 0)
++slow;
//nums[i]+nums[slow]+nums[fast] == 0 还要考虑对slow fast去重
else {
result.push_back(vector<int>{nums[i], nums[slow], nums[fast]});
//有重复 进行移位
// fast是和前一位比较 如果相同可以用前一位替换
// slow是和后一位比较 如果相同可以用后一位替换
while (slow < fast && nums[slow] == nums[slow + 1])
++slow;
while (slow < fast && nums[fast] == nums[fast - 1])
--fast;
//fast slow没有重复也要位移
++slow;
--fast;
}
}
}
return result;
}
};
四数之和
class Solution {
public:
vector<vector<int>> fourSum(vector<int> &nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
int len = nums.size();
for (int i = 0; i < len; ++i) {
if (nums[i] > target && nums[i] >= 0)break;
//去重第一个
if (i > 0 && nums[i] == nums[i - 1])continue;
//下面和复现三数之和
for (int j = i + 1; j < len; ++j) {
int tmp = nums[i] + nums[j];
if (tmp >= 0 && tmp > target)break;
if (j > i + 1 && nums[j] == nums[j - 1])continue;
int left = j + 1, right = len - 1;
while (left < right) {
if ((long) tmp + nums[left] + nums[right] > target)
--right;
else if ((long) tmp + nums[left] + nums[right] < target)
++left;
else {
//相等 但是对left和right去重
result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]});
while (left < right && nums[left] == nums[left + 1])++left;
while (left < right && nums[right] == nums[right - 1])--right;
//正常的移动
++left;
--right;
}
}
}
}
return result;
}
};