题目链接:https://leetcode.com/problems/reverse-linked-list/
其实做法挺简单的,就是将每个节点的next指针指向原来链表中的上一个就好了,注意对NULL的处理。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *last = NULL, *now = head;
while (now != NULL) {
ListNode* nextOne = now->next;
now->next = last;
last = now;
now = nextOne;
}
return last;
}
};
即旋转链表第m个节点到第n个节点之间的部分,逆转部分跟A的原理一样,不过要处理好左右,以及NULL的情况。
原题链接:https://leetcode.com/problems/reverse-linked-list-ii/
#include <stdio.h>
#include <assert.h>
struct ListNode {
int val;
ListNode *next;
ListNode(int x): val(x), next(NULL) {}
void append(int x) {
assert(this != NULL);
ListNode* now = this;
while (now->next != NULL)
now = now->next;
now->next = new ListNode(x);
}
void print() {
ListNode* now = this;
while (now != NULL) {
printf("%d ", now->val);
now = now->next;
}
printf("\n");
}
};
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if (m == n)
return head;
ListNode *left = NULL, *right = NULL;
ListNode *left_pre = NULL, *right_next = NULL;
ListNode *now = head, *last = NULL;
for (int i = 1; now != NULL; ++i) {
if (i == m-1)
left_pre = now;
else if (i == m)
left = last = now;
else if (i == n)
right = now;
else if (i > n) {
right_next = now;
break;
}
// case i in (m, n], reverse it
if (i > m) {
ListNode* nextOne = now->next;
now->next = last;
last = now;
now = nextOne;
continue;
}
now = now->next;
}
if (left_pre == NULL)
head = left_pre = right;
else
left_pre->next = right;
left->next = right_next;
return head;
}
};
int main() {
Solution s;
ListNode* head = new ListNode(1);
for (int i = 2; i <= 10; ++i)
head->append(i);
printf("between 2 and 9:\n");
head = s.reverseBetween(head, 2, 9);
head->print();
head = s.reverseBetween(head, 2, 9);
head->print();
printf("\ninclude the head:\n");
head = s.reverseBetween(head, 1, 9);
head->print();
head = s.reverseBetween(head, 1, 9);
head->print();
printf("\nreverse the total list:\n");
head = s.reverseBetween(head, 1, 10);
head->print();
head = s.reverseBetween(head, 1, 10);
head->print();
printf("\nreverse one element:\n");
head = s.reverseBetween(head, 1, 1);
head->print();
head = s.reverseBetween(head, 1, 1);
head->print();
return 0;
}
原题:https://leetcode.com/problems/reverse-bits/
给定一个无符号整数,要求将其二进制形式翻转一下,比如010111将变成111010,主要是位操作,掩码的基础知识,倒没什么特殊的技巧。
#include <stdio.h>
#include <assert.h>
typedef unsigned int uint32_t;
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t ans = 0, mask = 1u;
for (int i = 0; i < 32; ++i) {
ans = ans << 1;
if ((n & mask) != 0)
ans |= 1u;
mask = mask << 1;
}
return ans;
}
};
int main() {
Solution s;
assert(s.reverseBits(0u) == 0u);
assert(s.reverseBits(1u) == 2147483648u);
assert(s.reverseBits(43261596u) == 964176192u);
return 0;
}
原题:https://leetcode.com/problems/reverse-integer/
这道题主要是要考虑如何判断是否会溢出,查阅网上资料后,觉得“未雨绸缪”法比较可取:
#include <stdio.h>
#include <assert.h>
using namespace std;
class Solution {
public:
int reverse(int x) {
int My_INT_MAX = (1u << 31) - 1, My_INT_MIN = -(1u << 31);
bool neg = false;
if (x == 0)
return 0;
if (x < 0) {
if (x == My_INT_MIN)
return 0;
neg = true;
x = -x;
}
int ans = 0;
while (x > 0) {
if (ans > My_INT_MAX / 10)
return 0;
ans *= 10;
int key = x % 10;
if (ans > My_INT_MAX - key)
return 0;
ans += key;
x /= 10;
}
if (neg)
return -ans;
return ans;
}
};
int main() {
Solution s;
assert(s.reverse(0) == 0);
assert(s.reverse(-1) == -1);
assert(s.reverse(-123) == -321);
assert(s.reverse(234) == 432);
assert(s.reverse(1234567809) == 0);
assert(s.reverse(-2147483648) == 0);
assert(s.reverse(2147483647) == 0);
return 0;
}
原题:https://leetcode.com/problems/reverse-words-in-a-string/
即把the sky is blue变成blue is sky the
这个问题本身不难,难的是,能否做到O(1)的空间开销?
答案是可以的哈哈,第一次自己解决这样“精巧”的题目,之前稍微思维有点绕的题目都得看题解才能知道,否则就是各种暴力咕~~(╯﹏╰)b。
我的思路是:先将整个字符串按字符反转,比如the sky is blue变成eulb si yks eht,这样子有什么用呢?其实跟华容道这个游戏有点相似,你先把要“运输”的东西运送到目的地,然后再“转个身”,就好啦,具体的转身在这里就是——对每个单词(按照空格将其分开),内部再反转一次,就会变成:blue is sky the,具体实现代码如下:
#include <stdio.h>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <assert.h>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <cmath>
using namespace std;
class Solution {
public:
// need in-place and O(1) space to solve
void reverseWords(string& s) {
// first, you should get enough space to reverse each word
// but notice that each word is exactly equal to itself in size!!!!!!
// this is the most important property to solve this problem in O(1) space
if (s.empty() || s == " ") {
s = "";
return;
}
int start = -1, len = s.size();
reverseHelper(s, 0, len-1);
for (int i = 0; i < len; ++i) {
if (start == -1 && s[i] != ' ')
start = i;
else if (start != -1 && (s[i] == ' ' || i == len-1)) {
int tail = i - 1;
if (i == len-1 && s[i] != ' ')
tail = i;
reverseHelper(s, start, tail);
// printf("i=%d, s=%s, start=%d, tail=%d\n", i, s.data(), start, tail);
start = -1;
}
}
}
void reverseHelper(string& s, int beg, int end) {
for (int i = beg, j = end; i < j; ++i, --j)
swap(s[i], s[j]);
}
};
int main() {
Solution s;
string str("hello jacket");
printf("Original str=%s\n", str.data());
s.reverseWords(str);
printf("After reversing, str=%s\n", str.data());
return 0;
}
这个是题外话了,无关reverse的主题,不过也是个有趣的问题,细节需要处理好——比如删除的值如果是在链表的头部,那该怎么办?代码感觉还是有点复杂了,可以再简化一下:
#include <stdio.h>
struct DList
{
int val;
DList *prev, *next;
DList(int v): val(v), prev(NULL), next(NULL) {}
};
DList* delHelper(DList* pos) {
DList* next = pos->next;
DList* prev = pos->prev;
if (prev != NULL)
prev->next = next;
if (next != NULL)
next->prev = prev;
// delete pos; // if necessary
return next;
}
int delVal(DList*& head, int val) {
int cnt = 0;
DList* now = head;
bool first = true;
while (now != NULL) {
if (now->val == val) {
now = delHelper(now);
++cnt;
}
else {
if (first) {
first = false;
head = now;
}
now = now->next;
}
}
// 如果全部都被删掉了,那么head自然就是NULL了
if (first)
head = NULL;
return cnt;
}
void joint(DList* a, DList* b) {
a->next = b;
b->prev = a;
}
void print(DList* head) {
DList* now = head;
bool first = true;
while (now != NULL) {
if (first) {
first = false;
printf("%d", now->val);
}
else
printf(" -> %d", now->val);
now = now->next;
}
printf("\n");
}
int main() {
DList* list[10];
for (int i = 0; i < 10; ++i)
list[i] = new DList(i/2);
for (int i = 0; i < 9; ++i)
joint(list[i], list[i+1]);
DList* head = list[0];
print(head);
delVal(head, 0);
print(head);
delVal(head, 3);
delVal(head, 4);
print(head);
return 0;
}