您的位置:首页 > 编程语言

leetcode题解日练--2016.7.23

2016-07-24 01:58 148 查看
日练三题,冰冻三尺非一日之寒。

今日题目:

1、最大整除子集;

2、链表插入排序;

3、链表排序 。

今日摘录:

我愿意深深地扎入生活,吮尽生活的骨髓,过得扎实,简单,把一切不属于生活的内容剔除得干净利落,把生活逼到绝处,用最基本的形式,简单,简单,再简单。

——梭罗《瓦尔登湖》

368. Largest Divisible Subset | Difficulty: Medium

Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.

If there are multiple solutions, return any subset is fine.

Example 1:

nums: [1,2,3]

Result: [1,2] (of course, [1,3] will also be ok)

Example 2:

nums: [1,2,4,8]

Result: [1,2,4,8]

tag:数学、DP

题意:从一个集合中去寻找满足集合内部每两个元素都存在非1公约数的子集。

思路:

1、本来想从前往后去找,后来发现不太对劲,又从后往前去找,好像又没找到什么规律。后面一怒之下打了两小时乒乓球加桌球,好像开窍了。

还是看一个栗子加深理解吧,也不举太复杂的栗子,就[0,1,2,3,4,5,6,7,8,9,10]其实本来不应该有0,但是为了表示的方便,暂时加进来,不考虑就是了。

从大到小遍历这个数组,dp[i]中代表以元素i作为结尾的最大集合长度。dp[10] = 1,然后逆推往回求dp[9],从9一直到最后找能被10整除的数字,没这样的不存在,所以dp[9]=1,同理dp[8]=dp[7]=dp[6]=1.到dp[5]的时候,向后找找到了10能整除5,所以dp[5] = 2,同理dp[4]找到8、dp[3]找到6或者9,因为dp[6]=dp[9]=1,所以dp[3]找到他俩中的较大值再加1dp[3]=2,也等于2,dp[2]找到4\6\8\10,其中最大的dp[4]=2,所以dp[2] = 3,dp[1]后面的都能找到它的倍数,其中最大的dp[2]=3,所以dp[1]=4。到此为止,我们已经找到了最大的共存元素个数,这个时候就需要将其还原了,但是好像少了什么,没错,我找到dp[1]最大了,但是dp[1]是包含哪4个元素?好像找不到了,这就需要在找的过程顺便建立一种联系,可以想象成很多个链表。

1->2->4->8

5->10

3->9

所有dp值大于等于2的元素都将作为起始点指向它的父节点,也就是能整除它的父亲。

class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<int> T(nums.size(),0);
vector<int> parent(nums.size(),0);
int max=0,maxIdx=0;
for(int i=nums.size()-1;i>=0;--i)
{
for(int j=i;j<nums.size();++j)
{
if(nums[j]%nums[i]==0 && T[i]<1+T[j])
{
T[i] = 1+T[j];
parent[i]=j;
if(T[i]>max)
{
max = T[i];
maxIdx = i;
}
}
}
}
vector<int> res;
for(int i=0;i<max;i++)
{
res.push_back(nums[maxIdx]);
maxIdx = parent[maxIdx];
}
return res;
}
};


结果:68ms

147. Insertion Sort List | Difficulty: Medium

Sort a linked list using insertion sort.

tag:链表、排序

题意:将一个链表按照插入排序的方法从小到达排列。

思路:

1、以4->2->3->1为例,来看看如何使用插入排序。

首先新建一个结果链表,设立一个左边界,然后去从结果链表中找到一个比待插入元素大的位置,将待插入元素插入。

具体来看,先从4开始访问 ,当访问到4的时候,将它加入结果数组中。结果数组中都是有序的,这个时候

结果链表中有一个左边界和元素4,这个时候再访问3的时候,需要遍历结果链表,给它找到应该放的位置,那怎么找呢?就是逐个访问结果链表,如果找到小于我们找的值,就跳到下一个,直到找到一个比插入值大的元素或者找到最后没找到,这里对应的是4,将插入值插入到左边界和4之间。

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
ListNode res(INT_MIN);
while(head)
{
ListNode*iter = &res;
cout<<iter->val<<endl;
while(iter->next && iter->next->val <head->val) iter = iter->next;
//首先保存下来head的下一个节点,加入head之后好更改head的值
ListNode*next = head->next;
//然后准备插入head节点,对head和iter做一个比较看看是插入到前面还是后
head->next = iter->next;
iter->next = head;
head = next;
}
return res.next;
}
};


结果:168ms

第二次刷代码168ms

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if(head==NULL || head->next==NULL)  return head;
ListNode*res = new ListNode(INT_MIN);
while(head)
{
ListNode*cur = res;
ListNode*next  = head->next;
while(cur->next && cur->next->val<head->val) cur = cur->next;
head->next = cur->next;
cur->next = head;
head = next;
}
return res->next;
}
};


结果:80ms

148. Sort List | Difficulty: Medium

Sort a linked list in O(n log n) time using constant space complexity.

tag:链表、排序

题意:nlogn时间,常数空间对链表进行排序。

思路:

1、因为链表直接访问下标不太方便,所以在排序的时候使用快排思想不太容易实现。那么,还要什么思路呢?桶排序不失为一种方法,当时空间复杂度过高,相当于时间复杂换空间复杂,还有哪些常见的排序呢?不难想到归并排序正是我们所想找的。

归并排序主要就是归和并两步骤,归用递归去解决,每次将连表分为前半部分和后半部分。直到平凡情况,即两部分都只有1个元素,这个时候就需要开始并了。

并的思路很简单,逐个比较两部分元素,创建一个新链表,哪边小就将结果加进去,最后肯定会剩下一部分元素,再给接到链表最后,最后返回这整个链表去处理上一层的递归调用。

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head==NULL || head->next==NULL)  return head;
ListNode *h1 = head;
ListNode*h2 = head->next->next;
while(h2 && h2->next)
{
h1 = h1->next;
h2 = h2->next->next;
}
h2 = h1->next;
h1->next = NULL;
return merge(sortList(head),sortList(h2));
}
ListNode *merge(ListNode*h1,ListNode*h2)
{
ListNode  *newHead = new ListNode(INT_MIN);
ListNode  *node =newHead ;
while(h1 && h2)
{
if(h1->val<h2->val)
{
node->next = h1;
node = node->next;
h1 = h1->next;
}
else
{
node->next = h2;
node = node->next;
h2 = h2->next;
}
}
if(h1)  node->next = h1;
else    node->next= h2;
return newHead->next;
}
};


结果:60ms
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode 编程 日记