题目描述
Sort a linked list in O(n log n) time using constant space complexity.
对一个链表进行排序,时间复杂度为O(n log n),空间复杂度为O(1),所以这道题目的限制还是比较多。
由于链表的索引不是很方便,所以首先可以想到使用归并排序,那么时间复杂度为O(n log n)。然后又因为空间复杂度为O(1),那么对于指针的使用的要求比较高。需要进行较为复杂的指针重定向。
总的思路呢就是递归排序,排好最小单位以后然后再归并。这里呢需要注意的是如果单独排两个链表很简单,但是排多个链表的时候,需要想到怎么把前后的链表串联起来?以及如果判断边界?
前后字符串的串联就是使用返回头指针,再归并,再返回头指针。
判断边界这里使用二分快慢指针的时候,把中间节点的后继置为NULL,做归并的时候就更加方便不需要特意加入条件判断。
代码实现
代码效率还行,击败了68%左右的C++。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* findMidListNode(ListNode* head) {
if(!head || !head->next) return NULL;
ListNode *p1 = head, *p2 = head->next; //tail?head:head->next;
while(p2 != NULL && p2->next != NULL) {
p2 = p2->next->next;
p1 = p1->next;
}
p2 = p1->next;
p1->next = NULL;
return p2;
}
ListNode* Merge(ListNode* p1, ListNode* p2) {
ListNode* head = new ListNode(0);
ListNode* cur = head;
while(p1 != NULL && p2 != NULL) {
if(p1->val > p2->val) {
cur->next = p2;
cur = p2;
p2 = p2->next;
}
else {
cur->next = p1;
cur = p1;
p1 = p1->next;
}
}
cur->next = p1?p1:p2;
return head->next;
}
ListNode* SortAndMerge(ListNode* head) {
if(!head || !head->next) return head;
ListNode* mid = findMidListNode(head);
ListNode* p1 = SortAndMerge(head);
ListNode* p2 = SortAndMerge(mid);
return Merge(p1, p2);
}
ListNode* sortList(ListNode* head) {
if(!head || !head->next) return head;
return SortAndMerge(head);
}
};
191. Number of 1 Bits
description
Write a function that takes an unsigned integer and returns the number of ’1’ bits it has (also known as the Hamming weight).
For example, the 32-bit integer ’11’ has binary representation 00000000000000000000000000001011, so the function should return 3.
implementation
This problem is very easy, we just shift the number and use operation & to get the lowest bit, if it’s 1 we add 1 to the result. Then shift the number by one bit until the shifted number is larger than 0.
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while(n > 0) {
res += n&1;
n = n >> 1;
}
return res;
}
};
476. Number Complement
description
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
Note:
The given integer is guaranteed to fit within the range of a 32-bit signed integer.
You could assume no leading zero bit in the integer’s binary representation.
Example 1:
Input: 5
Output: 2
Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2.
Example 2:
Input: 1
Output: 0
Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0.
Here you need aware that the number is positive, and U have no need to worry about the non-positive situation as the signed shift.
implementation
1 the number is larger than 0 go to 2, otherwise break and return result.
2 get the reverse least significant bit of number and shift the bit to left with count.
3 shift number to right by one bit and count plus
4 go to step 1.
The code is showing below:
class Solution {
public:
int findComplement(int num) {
int res = 0, ind = 0;
while(num > 0) {
res |= (~num & 1) << ind;
num = num >> 1;
ind++;
}
return res;
}
};
342. Power of Four
description
Given an integer (signed 32 bits), write a function to check whether it is a power of 4.
Example:
Given num = 16, return true. Given num = 5, return false.
Follow up: Could you solve it without loops/recursion?
Power of 4 is has the feature that the padding zero is double
implementation
The algorithm runs below:
1 get the least two bit of the number a and left number num
2 if a is zero and num is 1, return true
if a is 1 and num is 0 return true
if num is zero and a is not 1 return false
3 go to step 1
class Solution {
public:
bool isPowerOfFour(int num) {
if(num <= 0) return false;
int lower = num&3;
for(int i = 0; i < 16; i++) {
num = num >> 2;
if((num && lower) || (num == 0 && lower != 1)) return false;
else if((num == 1 && lower == 0) || (num == 0 && lower == 1)) return true;
lower = num&3;
}
return true;
}
};
这道题目我还看到了非常变态的做法:
class Solution {
public:
bool isPowerOfFour(int num) {
double n = num;
return (*(long*)&n & 0x801FFFFFFFFFFFFF) == 0x10000000000000;
}
};
当然还有:
class Solution {
public:
bool isPowerOfFour(int num) {
return num > 0 && (num & (num - 1)) == 0 && (num - 1) % 3 == 0;
}
};