leetcode 力扣 036 马戏团人塔 题解 算法题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:马戏团人塔
有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上。
出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一点。
已知马戏团每个人的身高和体重,请编写代码计算叠罗汉最多能叠几个人。
示例:
输入:height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110]
输出:6
解释:从上往下数,叠罗汉最多能叠 6 层:(56,90), (60,95), (65,100), (68,11 0), (70,150), (75,190)
提示:
•height.length == weight.length <= 10000
题解 1
image.png
class Point{int h;int w;int max;Point(int h, int w){this.h = h;this.w = w;}}
class Solution {
public int bestSeqAtIndex(int[] height, int[] weight) {
Point[] arr = new Point[height.length];
for(int i=0;i<arr.length;i++)arr[i]=new Point(height[i], weight [i]);
Arrays.sort(arr,(a,b)->(a.h!=b.h?(a.h-b.h):(b.w-a.w)));
TreeSet<Point> set = new TreeSet<Point>((a,b)->((a.max!=b.max?
(b.max-a.max):(a.h!=b.h?(b.h-a.h):(b.w-a.w)))));
HashMap<Integer, Point> map = new HashMap<Integer, Point>();
int max=1;arr[0].max=1;set.add(arr[0]);
ArrayList<Point> rmLst = new ArrayList<Point>();
for(int i=1;i<height.length;i++){
int temp=1,h=arr[i].h,w=arr[i].w;
for(Point p:set)if(w>p.w&&h>p.h){temp = p.max+1;break;}
if(h>arr[i-1].h){for(Point p:rmLst)set.remove(p);rmLst.clea r();}
if(temp>max)max = temp;arr[i].max=temp;
if(map.containsKey(temp)){
Point p = map.get(temp);if(arr[i].w<p.w){map.put(temp,a rr[i]);set.add(arr[i]);rmLst.add(p);}
}else{set.add(arr[i]);map.put(temp,arr[i]);}
}
return max;
}
}
题解 2
温馨提示:
题目要求是“矮一点且轻一点”,是严格要求<而不是<=。
官方测试用例
自己可以用来小测的测试用例(答案为3而不是5):
[1, 2, 2, 2, 3]
[4, 5, 6, 7, 8]
思路
题目要求在2个维度上(即身高 + 体重)同时保持严格递增。
那么我们可以先将其中一个维度排好序,以保证在一个维度上保持递增(此时并非严格递增);
之后就可以专注于处理另一个维度。
具体而言:
先根据身高升序排序,若身高一样则根据体重降序排序。
身高排序好之后,剩余待处理的就是体重。
处理体重的问题就是处理最长递增子序列的问题。
那么仔细想想为什么身高相同时,体重需要降序排序呢?
其实很简单的道理,将身高相同的人看成1个集合,若他们都按照体重升序来排序,则之后的二分法处理中,有一定的概率会在这集合中取>= 2个人作为最终结果。
为什么说是“有一定的概率会在这集合中取>= 2个人作为最终结果”呢?
比如:
身高:[1, 2, 2, 3, 4]
体重:[1, 3, 4, 5, 7]
显然,在身高升序排序,且身高相同则体重升序排序的预处理后,对体重进行二分查找得到的最长递增子序列的结果是[1, 3, 4, 5, 7],而体重为3、4的那2个人身高相同,不符合题意。
比如:
身高:[1, 2, 2, 3, 4]
体重:[4, 1, 2, 5, 7]
显然,在身高升序排序,且身高相同则体重升序排序的预处理后,对体重进行二分查找得到的最长递增子序列的结果是[4, 5, 7],这其中并没有包含身高为2的那2个人。
(简单说就是运气好罢了,结果刚好符合题意)。
因为是体重升序,二分法处理时(从左往右遍历),身高相同的人的集合自己本身也有可能构成上升子序列,就使得最终答案内可能包含身高相同,体重递增的结果。
同样,将身高相同的人看成1个集合,若他们都按照体重降序来排序,在二分法顺序遍历的过程中,是无法在这个集合中取>= 2个人作为最终结果(即,要么取只能取1人,要么不取)。
因为是体重降序,二分法处理时(从左往右遍历),身高相同的人的集合自己本身是无法构成上升子序列,也就不会出现最终答案内包含身高相同,体重递增的情况。
3种写法:
语言:java
class Solution {
public int bestSeqAtIndex(int[] height, int[] weight) {
int len = height.length;
int[][] person = new int[len][2];
for (int i = 0; i < len; ++i)
person[i] = new int[]{height[i], weight[i]};
Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
int[] dp = new int[len];
int res = 0;
for (int[] pair : person) {
int i = Arrays.binarySearch(dp, 0, res, pair[1]);
if (i < 0)
i = -(i + 1);
dp[i] = pair[1];
if (i == res)
++res;
}
return res;
}
}
语言:java
class Solution {
private int[][] person, memo;
private int len;
public int bestSeqAtIndex(int[] height, int[] weight) {
len = height.length;
person = new int[len][2];
for (int i = 0; i < len; ++i)
person[i] = new int[]{height[i], weight[i]};
Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]); memo = new int[len + 1][len];
for (int[] l : memo)
Arrays.fill(l, -1);
return dfs(-1, 0, 0);
}
private int dfs(int pre_idx, int cur_idx, int weight_bound) {
if (cur_idx == len)
return0;
if (memo[pre_idx + 1][cur_idx] >= 0)
return memo[pre_idx + 1][cur_idx];
int taken = 0;
if (pre_idx < 0 || person[cur_idx][1] > weight_bound)
taken = 1 + dfs(cur_idx, cur_idx + 1, person[cur_idx][1]);
int not_taken = dfs(pre_idx, cur_idx + 1, weight_bound);
return memo[pre_idx + 1][cur_idx] = Math.max(taken, not_taken); }
}
语言:java
class Solution {
public int bestSeqAtIndex(int[] height, int[] weight) {
int len = height.length;
int[][] person = new int[len][2];
for (int i = 0; i < len; ++i)
person[i] = new int[]{height[i], weight[i]};
Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
int[] dp = new int[len];
dp[0] = 1;
int res = 1;
for (int i = 1; i < len; ++i) {
int max_val = 0, base_weight = person[i][1];
for (int j = 0; j < i; ++j)
if (base_weight > person[j][1])
max_val = Math.max(max_val, dp[j]);
dp[i] = max_val + 1;
res = Math.max(res, dp[i]);
}
return res;
}
}
题解 3
•先排序:高度升序排列,相同高度的宽度降序排列
•然后DP数组下标 i 位置记录长为 i+1 最长递增序列末尾数字最小值
•最后返回DP数组长度
•PS(新瓶装旧酒,和俄罗斯套娃信封问题一样)
class Solution {
public:
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
vector<pair<int,int>> tmp;
for(int i = 0; i < height.size(); i++) tmp.push_back({height[i], weight[i]});
sort(tmp.begin(), tmp.end(), [](const pair<int,int> &a, const p air<int,int> &b) {
return a.first == b.first ? a.second > b.second : a.first < b.first;
});
vector<int> dp; //长度为N的地方最小的数字
for(const auto &[h, w]: tmp) {
auto p = lower_bound(dp.begin(), dp.end(), w); //二分查找第一个大于等于的地方
if(p == dp.end()) dp.push_back(w);
else *p = w;
}
return dp.size();
}
};
题解 4
解题思路
看懂题意后先把身高作升序排列,就找体重的最长上升子序列充分利用python库,发挥一下切片性能一个坑就是要把第二位排列字段做降序,这样同样的身高只会
保留一个体重
比如:[9,8,7],如果7比dp最后一个元素大,那么先添加9,然后8替换掉9,然后7替换掉8,如果7,8,9有比dp小的,那么也只是替换那个比他大的元素,不会新增元素
就明白我们的dp只有替换和新增末尾两个操作就容易编写代码了
代码
语言:python3
class Solution:
import bisect
def bestSeqAtIndex(self, height: List[int], weight: List[int]) -> i nt:
dp=[]
for a,b in sorted(zip(height,weight),key = lambda x:[x[0],-x [1]]):
pos = bisect.bisect_left(dp,b)
dp[pos:pos+1] = [b]
return len(dp)
题解 5
解题思路
1.二分查找,思路很简单。
– 1.先按照身高height进行由低到高排序,当两个人对应的height相同的时候,按照weight由重到轻的顺寻进行排序
– 2.为题转换为求排序后的对应的weight的最长的严格的递增子序列的长度 3.对于求严格递增子序列的长度有动态规划和贪心+二分解决 4.第
一种使用动态规划超时 5.第二种使用贪心+二分: <1>遇到比数组末尾
元素大的,直接推入数组;<2>遇到比数组末尾的元素小的值,记作A,
找到数组里面大于等于这个值的最小的数对应的索引,并替换该索引对
应的值为A。
<3>贪心思想体现在使得最后的数组里面的相邻的两个值
的差距尽可能的缩小,这样使得数组的长度尽可能的大。
使用动态规
划的代码如下:
//动态规划:通过的用例情况28/43
class Solution {
public:
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
vector<pair<int,int>>vc;
vector<int>temp;
for(int i=0;i<height.size();i++){
vc.emplace_back(height[i],weight[i]);
}
sort(vc.begin(),vc.end(),[](const auto& vc1,const auto& vc2){r eturn vc1.first==vc2.first?vc1.second>vc2.second:vc1.first<vc2.firs t;});
for(const auto& pr:vc){
temp.push_back(pr.second);
}
vector<int>dp(temp.size(),0);
for(int i=0;i<temp.size();i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(temp[j]<temp[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
}
return *max_element(dp.begin(),dp.end());
}
};
代码
语言:cpp
//使用二分查找
class Solution {
public:
//二分查找数组res中大于等于目标值target的最小的索引
int binarysearch(vector<int>& res,int target){
int l=0;
int r=res.size()-1;
while(l<=r){
int mid=(r-l)/2+l;
if(res[mid]==target){
return mid;
}
if(res[mid]<target){
l=mid+1;
}
else{
r=mid-1;
}
}
return l;
}
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
vector<pair<int,int>>vc;
vector<int>temp;
for(int i=0;i<height.size();i++){
vc.emplace_back(height[i],weight[i]);
}
//对每个人对应的身高和体重按照升高由低到高的顺序排序,身高相同,按照体重由到轻的顺序进行排序。
sort(vc.begin(),vc.end(),[](const auto& vc1,const auto& vc2){return vc1.first==vc2.first?vc1.sec ond>vc2.second:vc1.first<vc2.first;});
//将排序后的结果转化为数组temp记录
for(const auto& pr:vc){
temp.push_back(pr.second);
}
vector<int>res;
//使用二分+贪心求得最长的严格递增子序列的长度
for(int i=0;i<temp.size();i++){
if(res.empty()||temp[i]>res.back()){
res.push_back(temp[i]);
}
else{
int index=binarysearch(res,temp[i]);
res[index]=temp[i];
}
}
//返回结果
return res.size();
}
};
题解 6
解题思路
1.题目给出两个维度,两个维度上都满足严格递增的要求才可以叠上去。
2.考虑需要严格递增,先按照ℎeigℎt升序排序,同时ℎeigℎt相同的人按照
weigℎt降序排序。
3.这样排序下来,直接在数组中查找关于weigℎt的最长递增子序列就能得到答
案。
4.一个升序,一个降序的是与我们的解决方法相关(我们在排序之后,直接查
找体重的最长递增子序列就能得到答案),如:ℎeigℎt=
[3,2,2,3,1,6],weigℎt=[7,3,5,6,2,10]。
两个都升序的排序结果是ℎeigℎt=
[1,2,2,3,3,6],weigℎt=[2,3,5,6,7,10],直接查找体重的最长递增子序列结果是6,可以看到,同一身高内部可能存在体重的递增。
因此,会被加入结果。
而使用身高升序,体重降序,排序结果为ℎeigℎt=[1,2,2,3,3,6],weigℎt= [2,5,3,7,6,10],可以看到体重的最长递增子序列结果是4。
### 代码 #### 语言:cpp
class Solution {
public:
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
//构造最长递增序列,用身高升序排序,同时体重降序排序,然后在体重中查找最长递增子序列
vector<Person> persons;
for(int i = 0; i < height.size(); ++i){
persons.push_back(Person(height[i], weight[i]));
}
sort(persons.begin(), persons.end());
//然后用一个数组dp[i]表示长度为i+1长度的递增子序列的结尾最小值
vector<int> dp;
dp.push_back(persons[0].weight);
int end = 0;
for(int i = 1; i < persons.size(); ++i){
if(persons[i].weight > dp[end]){
dp.push_back(persons[i].weight);
++end;
}
else{
//查找第一个大于等于persons[i].weight的位置
int left = 0;
int right = end;
while(left < right){
int mid = left + (right - left) / 2;
if(dp[mid] >= persons[i].weight){
right = mid;
}
else{
left = mid + 1;
}
}
dp[left] = persons[i].weight;
}
}
return end + 1;
}
private:
struct Person{
int height;
int weight;
Person(int _height, int _weight): height(_height), weight(_weight){}
bool operator < (const Person &person) const{
if(height != person.height){
return height < person.height;
}
else{
return weight > person.weight;
}
}
};
};
题解 7
解题思路
1.现将数据按身高升序,体重降序排列。
2.对体重取最长递增子序列: 1)dp[i]表示长度为i时末尾最小的数是多少 2)如果新数比末尾数大,直接append 3)如果新数没有末尾数大,寻找第一个比新数小的数d[k],并更新d[k+1] = nums[i]。
代码
语言:python3
class Solution:
def bestSeqAtIndex(self, height: List[int], weight: List[int]) -> i nt:
li = []
for i, j in zip(height, weight):
li.append([i,j])
li.sort(key = lambda x:(x[0],-x[1]))
nums = [i[1] for i in li]
dp = []
for i in range(len(nums)):
# 如果新数比末尾数大,直接append
if not dp or nums[i]>dp[-1]:
dp.append(nums[i])
# 如果新数没有末尾数大,寻找第一个比新数小的数d[k],并更新d[k+1] = nums[i]
left, right = 0, len(dp)-1
while left <= right:
mid = (left + right) // 2
if dp[mid] >= nums[i]:
right = mid - 1
else:
left = mid + 1
if left < len(dp):
dp[left] = nums[i]
return len(dp)
题解 8
WX20210518-160749@2x.png
解题思路
贪心法 1. 将height和weight结合在一起做升序排列 - 先按照 height 升序排列 - height相等,则重量大的在前面(为什么这么做?后续解释) - 这么做实现了降维 2. 再次遍历前面排序号的数组 - 二分法去查找满足当前weight的下边界,然后更新对应的重量 - 对于一样height情况会造成后面人覆盖原来重的人,这样子后面才有机会放更更轻的人,这也是为什么重量大在前面的原因
代码
语言:cpp
class Solution {
public:
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
int n = height.size();
vector<pair<int, int>> persons;
for (int i = 0; i < n; ++i)
{
persons.emplace_back(height[i], weight[i]);
}
// 排序实现
sort(persons.begin(), persons.end(), [](const pair<int,int>& a, const pair<int,int>& b)
{
if (a.first == b.first)
{
return a.second >= b.second;
}
else
{
return a.first < b.first;
}
});
// for (pair<int,int>& a : persons)
// {
// cout << a.first << " " << a.second << endl;
// }
// d[i] 表示前i个数字,体重递增的情况下,i选择一个尽可能小的重量(这样子后面才更加有
机会)
int d[n+1];
// 默认设置一个大值
memset(d, 0x3f3f3f3f, sizeof(d));
for (int i = 0; i < n; ++i)
{
int* iter = lower_bound(d+1, d+1+n, persons[i].second);
*iter = persons[i].second;
}
// 最后结束的点是一个正常数字的点
int* last = lower_bound(d+1, d+1+n, 100000000);
return last - (d+1);
}
};
题解 9
解题思路
与[406] 根据身高重建队列问题类似思路大体一样,可以参考这个题解
• 1.粗处理排序,依据为:身高降序(这里就是人塔从下向上身高递减),身高相等则体重轻的在前边(从下向上体重升序)——问题1:这里不符而直觉,直觉应该体重也是降序才对,看完下边步骤再回来看
• 2.细处理遍历排序结果,将当前的人p放入到结果数组result中当然result的所有元素符合题意,即前一个人的身高体重均比后一个人大从前向后搜索result,找到第一个不应该排在p之前的人(即身高或体重不大于p
的身高体重) 2.1 没找到,直接把p追加到result结尾 2.2 找到的话,把这
个人排除,替换成`p——这是这个问题的关键所在,是个贪心策略,可以想一想为什么这样是合理的最后的result数组即为所求;另外在搜索result`的时候,用二分法会更快
•回头看问题1:考虑有身高相同的几个人,显然最终结果这几个人里最多有一个入选(也可能都不会入选),贪心策略,根据步骤2的处理,应该保留体重
最大的人入选所以一开始粗排,身高相等的情况下,体重升序,是为了2细排的时候能保留体重最重的那个人
初步实现
辅助代码 #### 语言:go
type Person struct {
height, weight int
}
主体代码 #### 语言:go
func bestSeqAtIndex(height []int, weight []int) int {
n := len(height)
if n == 0 {
return0
}
persons := make([]Person, n)
for i := range persons {
persons[i].height = height[i]
persons[i].weight = weight[i]
}
sort.Slice(persons, func(i, j int) bool {
// 身高高的在前边,身高相等则体重轻的在前边
if persons[i].height == persons[j].height {
return persons[i].weight < persons[j].weight
}
return persons[i].height > persons[j].height
})
var result []Person
for _, p := range persons {
// 在结果中找到第一个p不能叠在上面的人, 二分法
j := sort.Search(len(result), func(i int) bool {
c := result[i]
return c.height <= p.height || c.weight <= p.weight
})
// 将第j个人替换成p
if j == len(result) {
result = append(result, p)
} else {
result[j] = p
}
}
return len(result)
}
步骤1的排序时间复杂度为O(n * lgn), 步骤2遍历每个元素,对每个元素,在结果中用二分法找到应该替换的位置,时间复杂度O(n * lgn)综合时间复杂度O(n * lgn)persons数组和result数组为额外开辟的空间,空间复杂度O(n)
上面的步骤2,可以在persons原地调整,节省result数组 #### 语言:go // 粗处理的代码略
k := 0
for _, p := range persons {
// 在结果中找到第一个不能叠在p上面的人, 二分法
j := sort.Search(k, func(i int) bool {
c := persons[i]
return c.height <= p.height || c.weight <= p.weight
})
// 将这个个人替换成p
persons[j] = p
if j == k {
k++
}
}
return k
题解 10
func bestSeqAtIndex(height []int, weight []int) int {
n := len(height)
if n == 0 {
return 0
}
person := make([][2]int, n)
for i := range person {
person[i] = [2]int{height[i], weight[i]}
}
sort.Slice(person, func(i, j int) bool {
if person[i][0] == person[j][0] {
return person[i][1] < person[j][1]
}
return person[i][0] > person[j][0]
var f []int
for i := 0; i < n; i++ {
if len(f) == 0 || person[f[len(f)-1]][0] > person[i][0] && pers on[f[len(f)-1]][1] > person[i][1] {
f = append(f, i)
} else {
l, r := 0, len(f)-1
for l < r {
mid := (l+r)>>1
if person[f[mid]][0] > person[i][0] && person[f[mid]][1] > person[i][1] {
l = mid+1
} else {
r = mid
}
}
f[r] = i
}
}
return len(f)
}
题解 11
解题思路
这道题其实是最长递增子序列的二维版本。
我们首先按照身高来进行升序排序,
那么接下来就只需要考虑体重了,找到体重的最长严格递增子序列即可。
同时有一
个细节要注意。
我们求得的体重递增序列中,不能存在两个体重对应的身高相同的情况,因为这样就不满足身高严格递增。
这道题其实用动态规划来解会比较容易
处理上述的注意事项。
可惜会超时。
那么我们只好用贪心+二分查找的方法来解题。
这里用到了一个小技巧,身高相同时,体重按降序排列。
这样我们求体重递增序列的时候,无需考虑身高,也不会出现求得的结果中有两个相同身高的情况。
如果不用这个技巧的话,那么二分查找的时候,我们同时要考虑身高来排除错误的情况,情况比较复杂,目前我自己是还没有写出不使用前述技巧的解法。
太弱了。
今天这道题就因为这个降序的问题,消耗了我大半天,我真的服了。
动态规划,会超时
语言:golang
import (
"sort"
)
// 动态规划,会超时
func bestSeqAtIndex(height []int, weight []int) int {
n := len(height)
if n == 0 {
return 0
}
t := &TwoInts{height, weight}
sort.Sort(t)
dp := make([]int, len(weight))
ans := 0
for i := 0; i < n; i++ {
dp[i] = 1
for j := 0; j < i; j++ {
if height[i] > height[j] && weight[i] > weight[j] {
dp[i] = max(dp[i], dp[j]+1)
}
}
ans = max(ans, dp[i])
}
return ans
}
type TwoInts struct {
one, two []int
}
func (t *TwoInts) Len() int {
return len(t.one)
}
func (t *TwoInts) Less(i, j int) bool {
return t.one[i] < t.one[j]
}
func (t *TwoInts) Swap(i, j int) {
t.one[i], t.one[j] = t.one[j], t.one[i]
t.two[i], t.two[j] = t.two[j], t.two[i]
}
func max(i, j int) int {
if i > j {
return i
}
return j
}
贪心+二分查找(体重降序)
import (
"sort"
)
// 贪心+二分查找
func bestSeqAtIndex(height []int, weight []int) int { n := len(height)
if n == 0 {
return 0
}
t := &TwoInts{height, weight}
sort.Sort(t)
// minEnd[i]表示长度为i的子序列末尾元素的最小值
minEnd := make([]int, n+1)
maxLen := 0
for _, w := range weight {
l, r := 1, maxLen
for l <= r {
mid := (r-l)/2 + l
if minEnd[mid] >= w {
r = mid - 1
} else {
l = mid + 1
}
}
minEnd[l] = w
if l > maxLen {
maxLen = l
}
}
return maxLen
}
type TwoInts struct {
one, two []int
}
func (t *TwoInts) Len() int {
return len(t.one)
}
func (t *TwoInts) Less(i, j int) bool {
if t.one[i] == t.one[j] {
return t.two[i] > t.two[j]
}
return t.one[i] < t.one[j]
}
func (t *TwoInts) Swap(i, j int) {
t.one[i], t.one[j] = t.one[j], t.one[i]
t.two[i], t.two[j] = t.two[j], t.two[i]
}
题解 12
解题思路
身高不能相同
代码
语言:golang
func bestSeqAtIndex(height []int, weight []int) int { n := len(height)
if n <= 1 { return n }
h_w := make([][2]int, n)
for i := 0; i < n; i++ {
h_w[i][0], h_w[i][1] = height[i], weight[i] }
sort.Slice(h_w, func(i, j int)bool {
if h_w[i][0] == h_w[j][0] {
return h_w[i][1] > h_w[j][1]
}
return h_w[i][0] < h_w[j][0]
})
var id []int
for i := 0; i < n; i++ {
if i == 0 || (h_w[id[len(id)-1]][0] < h_w[i][0] && h_w[id[len(i d)-1]][1] < h_w[i][1]) {
id = append(id, i)
} else {
l, r := 0, len(id)-1
for l < r {
mid := (l+r) >> 1
if h_w[id[mid]][0] < h_w[i][0] && h_w[id[mid]][1] < h_w [i][1] {
l = mid + 1
} else {
r = mid
}
}
id[r] = i
}
}
return len(id)
}。