AIRobot

AIRobot quick note


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

装箱问题

发表于 2018-12-25 分类于 algorithm
本文字数: 649 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
问题描述

  有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
  要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入格式

  第一行为一个整数,表示箱子容量;
  第二行为一个整数,表示有n个物品;
  接下来n行,每行一个整数表示这n个物品的各自体积。

输出格式

  一个整数,表示箱子剩余空间。

样例输入

24
6
8
3
12
7
9
7

样例输出
0

01背包

dp[j]代表j容量最多能容纳多少
状态转移方程dp[j] = max(dp[j], dp[j-vi[i]]+vi[i])
分为选和不选,取最大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
#include<cstdio>
using namespace std;

int dp[20010];
int vi[50];
int main()
{
int n,V;
cin>>V>>n;
for(int i=0;i<n;++i)
scanf("%d", &vi[i]);
for(int i=0;i<n;++i)
{
for(int j=V;j>=vi[i]; --j)
{
dp[j] = max(dp[j], dp[j-vi[i]]+vi[i]);
}
}
cout<<V-dp[V]<<endl;
return 0;
}

求排列的逆序数

发表于 2018-12-25 分类于 algorithm
本文字数: 1.3k 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
总时间限制: 1000ms 内存限制: 65536kB 
描述
在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。

对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序。

一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。

现给定1,2,…,n的一个排列,求它的逆序数。

输入
第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。
输出
输出该排列的逆序数。
样例输入
6
2 6 3 4 5 1
样例输出
8

对于冒泡排序,交换次数就是逆序对数
归并排序时,归并操作时统计左边数组中小于右边数组元素的个数。
增加一句ans+=mid-i+1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<cstdio>
#define N 100010
using namespace std;

int n,a[N],b[N];
long long ans;

void merge_sort(int l,int r)
{
if(l==r) return;
int mid=(l+r)/2,i,j,k;
i=l;k=l;j=mid+1;
merge_sort(l,mid);
merge_sort(mid+1,r);
while(i<=mid && j<=r)
{
if(a[i]<=a[j])
b[k++]=a[i++];
else
ans+=mid-i+1,b[k++]=a[j++];
}
while(i<=mid)
b[k++]=a[i++];
while(j<=r)
b[k++]=a[j++];
for(int o=l;o<=r;++o)
a[o]=b[o];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
merge_sort(1,n);
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
printf("\n%lld\n",ans);
return 0;
}

LeetCode 3 无重复字符的最长子串

发表于 2018-12-25 分类于 algorithm
本文字数: 1k 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

维护一个count数组存储每一个字符在当前字符串中出现的次数和left,right两个指针,代表当前字符串的起始位置。maxlen存储最大长度,right指针不断右移直到有字符出现2次,此时不断右移left指针直到数组中没有字符出现次数大于1,更新maxlen值,重复此操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int count[1000] = {0};
int maxlen = 0;
int left,right;
left = right = 0;
for(int i=0;i<s.size();++i)
{
++count[s[i]];
if(count[s[i]]==2)
{
maxlen = max(maxlen, right-left);
while(count[s[i]]==2)
{
--count[s[left]];
++left;
}
}
++right;
}

return max(maxlen, right-left);
}
};

LeetCode 2 两数相加

发表于 2018-12-25 分类于 algorithm
本文字数: 1.1k 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

建新链表存储两个链表节点的和,处理一下进位就好了,一位数组,进位只能为0或1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *l = new ListNode(0);
ListNode *p, *p1, *p2;
p = l; p1 = l1; p2 = l2;
l->next = NULL;
int last = 0;
while(p1||p2||last)
{
int sum = (p1?p1->val:0) + (p2?p2->val:0);
p->val = ((sum + last)%10);
last = (sum+last)/10;
p1 = p1?p1->next:NULL;
p2 = p2?p2->next:NULL;
if(p1||p2||last)
{
p->next = new ListNode(0);
p = p->next;
}
}
return l;
}
};

LeetCode 1 两数之和

发表于 2018-12-25 分类于 algorithm
本文字数: 626 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

t = target - nums[i] ,哈希存储了nums[i]对应的下标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> m;
for(int i=0;i<nums.size();++i)
{
int t = target - nums[i];
if(m.count(t))
return vector<int> {m[t], i};
else
m[nums[i]] = i;
}
}
};
1…242526
AIRobot

AIRobot

AIRobot quick note
130 日志
15 分类
23 标签
GitHub E-Mail
Creative Commons
0%
© 2023 AIRobot | 716k | 10:51