编程日记,尽量保证每天至少3道leetcode题,仅此记录学习的一些题目答案与思路,尽量用多种思路来分析解决问题,不足之处还望指出。标红题为之后还需要再看的题目。
Reverse bits of a given 32 bits unsigned integer.
For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as 00111001011110000010100101000000).
Follow up:
If this function is called many times, how would you optimize it?
Related problem: Reverse Integer
题意:给一个数字,逆转它的二进制表示位。
思路:
1、32次循环,每次循环都是现将res左移1位然后再加上num的最低位。
代码:
C++
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t res=0;
for(int i=0;i<32;i++,n>>=1)
{
res=res<<1;
res |= n&1;
}
return res;
}
};
结果:4ms
Remove all elements from a linked list of integers that have value val.
Example
Given: 1 –> 2 –> 6 –> 3 –> 4 –> 5 –> 6, val = 6
Return: 1 –> 2 –> 3 –> 4 –> 5
题意:删除链表中值为val的元素。
思路:
直接从头开始,首先确定头的值不是val,然后逐个遍历,如果碰到值为val的节点则利用一个前节点(Prev)来删除当前的节点。不难,但是自己写的代码很丑,三次才AC,还是贴上来好了。
代码:
C++
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *Prev,*Node;
if(!head) return head;
while(head)
{
if(head->val==val)
head = head->next;
else
break;
}
Node = head;
Prev = NULL;
while(Node)
{
if(Node->val==val)
{
Prev->next = Node->next;
delete Node;
Node = Prev->next;
}
else
{
Prev = Node;
Node = Node->next;
}
}
return head;
}
};
结果:36ms
2、参考了https://leetcode.com/discuss/47642/simple-and-elegant-solution-in-c的做法,用一个二级指针,指针指向的是节点,最初指针指向的是head节点。当指针指向的节点等于val的的时候,指针指向的节点直接赋值为下一个节点,也就相当于是删除了当前的节点;当指针指向的节点不等于val的时候,需要更改指针内存放的内容为下一个节点。进行下一次的判断直到指针的内容为空。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode ** list = &head;
while(*list)
{
if((*list)->val==val) *list = (*list)->next;
else
list = &(*list)->next;
}
return head;
}
};
结果:32ms
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
题意:给一个链表,判断是否是回文。O(N)的时间和O(1)的空间。
思路:
首先,因为链表是单向的,那么要判断回文就需要将第一个节点和最后一个节点比较,然后两个节点向中间靠拢。首先我们需要找到中间的节点,即不需要逆转的最后一个节点。当节点总数是奇数的时候,例如n=7,显然我们只需要比较前三个节点和后三个节点,第4个节点不需要移动,中间节点下标是(6-0)/2=3,当n=8的时候,需要比较前四个节点和后四个节点,第四个节点不需要移动,因此中间节点下标还是(7-0)/2 = 3。因此第一步就是找到中间结点。
其次,找到中间节点之后,需要将中间节点之后的节点逆序,然后从中间节点的下一个节点开始依次和头部节点相比较。
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head==NULL||head->next==NULL) return true;
ListNode*slow,*fast;
slow=head,fast = head;
while(fast->next!=NULL && fast->next->next!=NULL)
{
slow = slow->next;
fast = fast->next->next;
}
slow->next = ReverseList(slow->next);
while(slow->next!=NULL)
{
if(slow->next->val!=head->val) return false;
slow = slow->next;
head = head->next;
}
return true;
}
ListNode* ReverseList(ListNode* head)
{
ListNode*Prev,*next;
Prev = NULL;
while(head!=NULL)
{
next = head->next;
head->next = Prev;
Prev = head;
head = next;
}
return Prev;
}
};
结果:29ms
Write a function to find the longest common prefix string amongst an array of strings.
题意:求一组字符串的最长公共前缀
思路:
逐个字符开始比较,先比较第0个字符是否符合,知道找到不符合的位为止返回前缀。
代码:
C++
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string prefix = "";
if(strs.size()<=0) return prefix;
//k代表判断的前缀字符数,从第0个字符开始,判断每一个strs的元素的第k位是否相等,如果全部相等了则最长公共前缀加1
for(int k = 0;k<strs[0].size();k++)
{
//i代表第i个字符串,每次循环的i需要小于strs的个数以及至少为k位,因为之前的前缀已经有k位了,某个字符串没有达到k位那么不必继续计算了
int i=1;
for(;i<strs.size()&&strs[i].size()>k;i++)
{
if(strs[i][k]!=strs[0][k]) return prefix;
}
if(i==strs.size()) prefix +=strs[0][k];
}
return prefix;
}
};
结果:6ms