Leetcode上的各种“Reverse”
来源:互联网 发布:java项目实战视频下载 编辑:程序博客网 时间:2024/05/22 16:38
A. 单链表整体的逆转
题目链接: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; }};
B. 单链表的部分逆转
即旋转链表第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;}
C. 二进制的反转
原题: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;}
D. 反转int数字
原题: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;}
E. 反转句子中的单词
原题: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;}
F. 在双向链表中删除一个值(并返回删除的个数)
这个是题外话了,无关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;}
- Leetcode上的各种“Reverse”
- LeetCode上reverse bits的C++解法
- leetcode上reverse integer的C语言代码
- LeetCode-92-Reverse Linked List II 链表反转 各种边界条件
- listview上的各种操作
- Android上的各种路径
- 电视上的各种接口
- 各种三方库 github上的
- Eclipse上的各种问题
- leetcode之92. Reverse Linked List II(C++读错题版本,交换一个链表中指定的两个位置上的元素)
- LeetCode:Reverse Integer
- LeetCode: Reverse Integer
- [Leetcode] Reverse Integer
- LeetCode : Reverse Integer
- [LeetCode] Reverse Integer
- Leetcode: Reverse Integer
- LeetCode 7 - Reverse Integer
- leetcode 104: Reverse Integer
- Objective-C对象之类对象和元类对象
- oracle自治事务(AT)
- Aidl与信使的区别
- SGU 223. Little Kings
- 嵌入式C语言常见面试题分析
- Leetcode上的各种“Reverse”
- getRawX、getRawY和getX、getY的区别
- 希尔排序
- UISrollView使用autolayout
- Java多线程(学习笔记)
- 仿支付宝登录页面
- jstat
- JPA
- CF #632A(A. Grandma Laura and Apples,)数学题