首页 > 试题广场 >

列表补全

[编程题]列表补全
  • 热度指数:5808 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

在商城的某个位置有一个商品列表,该列表是由L1、L2两个子列表拼接而成。当用户浏览并翻页时,需要从列表L1、L2中获取商品进行展示。展示规则如下:

1. 用户可以进行多次翻页,用offset表示用户在之前页面已经浏览的商品数量,比如offset为4,表示用户已经看了4个商品

2. n表示当前页面需要展示的商品数量

3. 展示商品时首先使用列表L1,如果列表L1长度不够,再从列表L2中选取商品

4. 从列表L2中补全商品时,也可能存在数量不足的情况

请根据上述规则,计算列表L1和L2中哪些商品在当前页面被展示了


输入描述:
每个测试输入包含1个测试用例,包含四个整数,分别表示偏移量offset、元素数量n,列表L1的长度l1,列表L2的长度l2。


输出描述:
在一行内输出四个整数分别表示L1和L2的区间start1,end1,start2,end2,每个数字之间有一个空格。
注意,区间段使用半开半闭区间表示,即包含起点,不包含终点。如果某个列表的区间为空,使用[0, 0)表示,如果某个列表被跳过,使用[len, len)表示,len表示列表的长度。
示例1

输入

2 4 4 4
1 2 4 4
4 1 3 3

输出

2 4 0 2
1 3 0 0
3 3 1 2
简单的一题
#include <algorithm>
#include <cstdio>
using namespace std;
int main() {
    int offset, n, l1, l2;
    while (~scanf("%d%d%d%d", &offset, &n, &l1, &l2))
        printf("%d %d %d %d\n", min(l1, offset), min(l1, offset+n), min(
               max(offset-l1, 0), l2), min(max(offset+n-l1, 0), l2));
    return 0;
}
发表于 2018-05-23 12:50:15 回复(11)

认真仔细读题 分析所有可能情况 这题没啥难度 就是要考虑周全 合理分类

#include<iostream>
#include<algorithm>
using namespace std;

int main(){
    int off, n, l1, l2;
    int start1, end1, start2, end2;
    while(scanf("%d%d%d%d", &off, &n, &l1, &l2) != EOF){
        if(off >= l1 + l2){//l1和l2都被跳过
            start1 = l1, end1 = l1;
            start2 = l2, end2 = l2;
        }
        else if(off >= l1){//l1被跳过
            start1 = l1, end1 = l1;
            start2 = off - l1, end2 = min(l2, off + n - l1);
        }
        else if(off + n <= l1){//l2为空
            start2 = 0, end2 = 0;
            start1 = off, end1 = off + n;
        }
        else{//两边都有的情况
            start1 = off, end1 = l1;
            start2 = 0, end2 = min(l2, off + n - l1);
        }
        printf("%d %d %d %d\n", start1, end1, start2, end2);
    }
    return 0;
}
/*
2 4 4 4
1 2 4 4
4 1 3 3
*/
发表于 2019-03-09 16:21:10 回复(0)
一开始连题意都没看懂
每一行是一个测试用例
比如第一个输入:2 4 4 4,输出2 4 0 2
表示已经看了两个商品(offset=2),每个页面可以展示4个商品,所以第一个列表里面前两个已经看过了,展示在当前页面的只有[2, 4),当前页面还剩两个位置,就展示第二个列表里的商品[0, 2)

#include <iostream>

using namespace std;

int main()
{
    int offset, n, l1, l2;
    while(cin >> offset >> n >> l1 >> l2) {
        if(offset < l1) {
            cout << offset << " " << min(offset + n, l1) << " ";
            if(offset + n - l1 < 0) {
                cout << "0 0" << endl;
            } else {
                cout << min(offset + n - l1, 0) << " " << min(max(offset + n - l1, 0), l2) << endl;
            }
        } else if(offset >= l1) {
            cout << l1 << " " << l1 << " ";
            cout << min(offset - l1, l2) << " " << min(offset + n - l1, l2) << endl;
        }
    }

    return 0;
}

编辑于 2019-03-13 00:44:20 回复(0)
很简单的一道题,按照优先级依次从第一个列表和第二个列表中取商品就行,在取的过程中检查是否已经超过当前列表的范围。
while True:
    try:
        offset, n, len1, len2 = map(int, input().strip().split())
        if len1 - offset > 0:
            # 第一个列表没有翻过
            start1 = offset                    # 第一个列表的起始位置
            end1 = min(start1 + n, len1)       # 第一个列表的结束位置
            if end1 - start1 >= n:
                # 第一个列表够补的话就不需要第二个列表的商品
                start2, end2 = 0, 0
            else:
                # 不够就需要从前往后取第二个列表的商品
                start2 = 0
                end2 = min(start2 + n - (end1 - start1), len2)
            print(f"{start1} {end1} {start2} {end2}")
        elif len1 == offset:
            # 第一个列表刚好翻过
            start1 = end1 = len1
            start2 = 0
            end2 = min(start2 + n, len2)
            print(f"{start1} {end1} {start2} {end2}")
        else:
            # 第一个列表翻完了,第二个列表也看过了一些
            start1 = end1 = len1
            start2 = min(offset - len1, len2)
            if start2 == len2:
                # 第二个列表也翻完了
                end2 = len2
            else:
                end2 = min(start2 + n, len2)
            print(f"{start1} {end1} {start2} {end2}")
    except:
        break

发表于 2021-04-19 14:51:32 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    int offset, n, l1, l2, s1, s2, e1, e2;
    while(scanf("%d%d%d%d", &offset, &n, &l1, &l2) != EOF){
        int m = offset+n;
        if(offset <= l1){
            s1 = offset;
            if(m <= l1){
                e1 = m;
                s2 = e2 = 0;
            }else{
                e1 = l1;
                s2 = 0;
                e2 = min(m-l1, l2);
            }
        }else if(offset <= l1+l2){
            s1 = e1 = l1;
            s2 = offset-l1;
            e2 = min(m-l1, l2);
        }else{
            s1 = e1 = l1;
            s2 = e2 = l2;
        }
        printf("%d %d %d %d\n", s1, e1, s2, e2);
    }
    return 0;
}

发表于 2020-11-09 00:00:57 回复(0)
关键在于将题中描述进行信息提取,转化为熟悉的问题模型;
查看长度始终为n,查看的范围在offset到offset+n之间;L1列表的范围是0到l1;L2列表的范围在l1到l1+l2;注意L2的范围l1输出时要输出0。
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int offset=sc.nextInt();
        int n=sc.nextInt();
        int l1=sc.nextInt();
        int l2=sc.nextInt();
        showList(offset,n,l1,l2);
    }
    public static void showList(int offset,int n,int l1,int l2){
        /* 分情况讨论:展示的长度始终为n,范围在offset——offset+n之间,
         * 对该范围进行分情况讨论。难点在于将题中描述提取出自己需要的信息,
         * 并进行转化。
         */
        if(offset <= l1 + l2){
            // 表明起点在L2表中
            if (offset >= l1){
                if (offset+n >= l1 + l2){
                    // 表明总长度大于L1,L2列表长度和
                    System.out.print(l1 + " " + l1 + " " + (offset-l1) + " " + l2);
                } else {
                    // 表明长度小于L1,L2列表长度和
                    System.out.print(l1 + " " + l1 + " " + (offset-l1) + " " + (offset+n-l1));
                }
            } else if(offset+n<=l1){
                //表明展示的数据全部来自L1
                System.out.print(offset + " " + (offset+n) + " 0 0");
            } else if (offset<l1){
                // 来自两表
                System.out.print(offset + " " + l1 + " 0 " + (offset+n-l1));
            }
        } else {
            // 表示两表跳过
            System.out.print(l1+" "+l1+" "+l2+" "+l2);
        }
    }
}



发表于 2019-11-27 20:13:06 回复(0)
题目写得也太绕了吧,读了好久
import java.util.Scanner;
public class Main {    
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            int offset=sc.nextInt();
            int n=sc.nextInt();
            int len1=sc.nextInt();
            int len2=sc.nextInt();
            int[] res=getResult(offset,n,len1,len2);
            for(int i=0;i<res.length;i++){
                if(i==res.length-1){
                    System.out.println(res[i]);
                }else{
                    System.out.print(res[i]+" ");
                }
            }
                
        }
    }

    private static int[] getResult(int offset, int n, int len1, int len2) {
        int[] res=new int[4];
        //start1
        res[0]=len1-offset>0?offset:len1;
        //end1
        res[1]=len1-offset-n>0?offset+n:len1;
        //start2
        int k=offset-len1;
        res[2]=k>0?len2-k>0?k:len2:0;
        //end2
        int x=offset+n-len1;
        res[3]=x>0?len2-x>0?x:len2:0;
        return res;
    }
}

发表于 2019-05-03 20:27:03 回复(0)
比较简单的题,分类讨论即可,就是一开始读题的时候有点麻烦,需要理解一下。
#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
    int offset, currentpage, len1, len2;
    while (cin >> offset >> currentpage >> len1 >> len2)
    {
        int start1 = 0, end1 = 0, start2 = 0, end2 = 0;
        if (offset < len1)
        {
            start1 = offset;
            if (currentpage > len1 - offset)
            {
                end1 = len1;
                end2 = currentpage - (len1 - offset);
            }
            else
                end1 = start1 + currentpage;
        }
        else
        {
            start1 = end1 = len1;
            int temp = offset - len1;
            if (temp > len2)
            {
                start2 = len2;
                end2 = len2;
            }    
            else
            {
                start2 = temp;
                if (currentpage < len2 - start2)
                    end2 = start2 + currentpage;
                else
                    end2 = len2;
            }
        }
        cout << start1 << " " << end1 << " " << start2 << " " << end2 << endl;
    }
    return 0;
}

发表于 2019-04-30 11:31:35 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author wylu
 */
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = br.readLine()) != null) {
            String[] strs = line.split(" ");
            int offset = Integer.parseInt(strs[0]), n = Integer.parseInt(strs[1]);
            int len1 = Integer.parseInt(strs[2]), len2 = Integer.parseInt(strs[3]);

            int s1 = Math.min(offset, len1);
            int e1 = Math.min(offset + n, len1);
            int s2 = Math.min(len2, Math.max(0, offset - len1));
            int e2 = Math.max(0, Math.min(len2, offset + n - len1));
            System.out.println(s1 + " " + e1 + " " + s2 + " " + e2);
        }
    }
}

编辑于 2019-01-22 10:47:32 回复(0)
offset这个点,隐藏着如果大于l1+l2意味着已经把l1和l2跳过了。其他理一理感觉还行。
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int offset = in.nextInt();
            int n = in.nextInt();
            int l1 = in.nextInt();
            int l2 = in.nextInt();
            // 根据offset计算起点
            int l3 = l1 + l2;
            // int plus = offset % l3;
            int plus = offset;
            // 判断偏移是否已经大于一遍
            if (plus < l3) {
                // 判断偏移是否超过l1
                if (plus < l1) {
                    // 判断l1剩余空间是否够n
                    if (l1 - plus + 1 >= n) {
                        System.out.print(plus + " " + (plus + n - 1 + 1) + " "  + "0 0" );
                    } else {
                        System.out.print(plus + " " + l1);
                        n -= (l1 - 1 - plus + 1);
                        // 判断l2剩余空间是否够n'
                        if (l2 >= n) {
                            System.out.print(" 0 " + (n - 1 + 1));
                        } else {
                            System.out.print(" 0 " + l2);
                        }
                    }
                } else {
                    // 同理
                    System.out.print(l1 + " " + l1 + " ");
                    plus -= l1;
                    if (l2 - plus + 1 >= n) {
                        System.out.print(plus + " " + (plus + n - 1 + 1));
                    } else {
                        System.out.print(plus + " " + l2);
                    }
                }
            } else {
                System.out.print(l1 + " " + l1 + " " + l2 + " " + l2);
            }
            System.out.println();
        }
    }
}


发表于 2023-11-28 22:39:14 回复(0)
尽量简短了
import sys

for line in sys.stdin:
    offset, n, l1, l2 = [int(num) for num in line.split()]
    s1, e1 = min(offset, l1), min(l1, n + offset)
    s2, e2 = max(min(offset - l1, l2), 0), min(max(0, n + offset - e1), l2)
    print(s1, e1, s2, e2)


发表于 2023-07-08 10:41:40 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
       
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
        int start1=0,end1=0,start2=0,end2=0;
            int offset=in.nextInt();
            int n=in.nextInt();
            int l1=in.nextInt();
            int l2=in.nextInt();
            start1=offset;
            if(start1<=l1)
            {
                if(n+start1<=l1)
                {
                    end1=start1+n;
                }
                else
                {
                    end1=l1;
                    start2=0;
                   end2=n-(end1-start1);
                    if(end2>l2)
                    end2=l2;
                }
            }
            else
            {
                start1=l1;
                end1=l1;
                start2=offset-l1;
                if(start2>l2)
                {
                    start2=l2;end2=l2;
                }
                else{
                end2=start2+n;
                if(end2>l2)
                end2=l2;
                }
               
            }
            System.out.print(start1+" "+end1+" "+start2+" "+end2+"\n");
        }
    }
}
//多看一眼就会爆炸
发表于 2023-07-07 17:35:37 回复(0)
打死也不分类讨论,直接用max和min来做就行
def solve():
    o, n, l1, l2 = [int(x) for x in input().split()]
    s1 = min(l1, o)
    e1 = min(l1, o + n)
    s2 = max(0, min(l2, o - l1))
    e2 = max(0, min(l2, o + n - l1))
    print(s1, e1, s2, e2, sep = ' ')
while 1:
    try:
        solve()
    except EOFError:
        break


发表于 2022-10-16 17:17:03 回复(0)
offset,n,l1,l2=map(int,input().split())
s1=min(l1,offset)
e1=min(l1,offset+n)
s2=min(max(offset-l1,0),l2)
e2=max(0,min(l2,offset+n-l1))
print(s1,e1,s2,e2)
上述程序应该是最简单的方法了。
发表于 2021-05-29 22:57:32 回复(0)
import java.util.*;

public class Main{
    
    public static void main(String[] args){
    
    	Scanner sc = new Scanner(System.in);
        while(sc.hasNextInt()){
            int offset = sc.nextInt();
            int n = sc.nextInt();
            int l1 = sc.nextInt(), l2 = sc.nextInt();

            int[] ans = solution(offset,n,l1,l2);
            StringBuilder ss = new StringBuilder();
            for(int i = 0; i < ans.length; i++){
                if(i != ans.length - 1) ss.append(ans[i]).append(' ');
                else ss.append(ans[i]);
            }
            System.out.println(ss.toString());
        }
    }
    
    // 2 4 4 4 ==> 2 4 0 2
	// 1 2 4 4 ==> 1 3 0 0
	// 4 1 3 3 ==> 3 3 1 2
    private static int[] solution(int offset, int n, int l1, int l2){
    
    	int[] ans = new int[4];
    	// 如果之前页面浏览的商品数量 offset 大于后面两列的数量,则表示 l1 和 l2 都需要表示浏览过的商品
    	// 如 4,1(可以是任意值),2,1
    	if(offset >= l1 + l2){
    		ans[0] = ans[1] = l1;
    		ans[2] = ans[3] = l2;
    		// 如果 offset >= l1 表示 l1 需要全部用来表示浏览过的,而 l2 用来表示全部或部分当前页展示的商品数量
    		// 如 3,2,2,2(l2 只能展示部分)  或 3,4,2,3(l2 展示全部)
    	} else if(offset >= l1){
    		ans[0] = ans[1] = l1;
    		ans[2] = offset - l1;
    		ans[3] = Math.min(l2,n + ans[2]);
    		// 如果 offset < l1 表示 l1 部分用来展示之前浏览的,剩下可以展示部分或全部
    		// 如 1,2,3,2(l1 展示全部) 或 1,3,2,3(l1 展示部分)
    	} else if(offset < l1){
    		ans[0] = offset;
    		ans[1] = Math.min(offset + n, l1);
    		ans[2] = 0;
    		ans[3] = offset + n <= l1 ? 0 : Math.min(offset + n - l1,l2);
    	}
    	return ans;
    }
}

发表于 2020-08-02 11:46:55 回复(0)

public class Demo {
     public static void ShowList(int[][] input){
            if(input.length == 0) return;
            int start1=0,end1 = 0,start2 = 0,end2 = 0;
            for(int i =0;i<input.length;i++){
                if(input[i][0]<input[i][2]&&input[i][0]+input[i][1]<input[i][2]){
                    start1 = input[i][0];
                    end1 = start1+input[i][1];
                    start2 = 0;
                    end2 = 0;
                }else if(input[i][0]<input[i][2]&&input[i][0]+input[i][1]>input[i][2]){
                    start1 = input[i][0];
                    end1 = input[i][2];
                    start2 = 0;
                    end2 = start1+input[i][1]-input[i][2];
                }else{
                    start1 = input[i][2];
                    end1 = input[i][2];
                    start2 = input[i][0]-input[i][2];
                    end2 = start2+input[i][1];
                    if(end2>input[i][3])
                        end2 = input[i][3];
                }
                System.out.println(start1+" "+ end1+" "+start2+" "+end2);
            }
        }
    public static void main(String[] args) {
        int[][] A = {{2, 4, 4, 4},
                {1, 2, 4, 4},
                {4, 1, 3, 3}};
        ShowList(A);
    }
}
发表于 2020-08-02 09:40:28 回复(0)
import sys

def display(offset, n, num1, num2):
    if offset <= num1:
        start1 = offset
        
        if n < num1 - offset:
            end1 = n + offset
            start2 = 0
            end2 = 0
        else:
            end1 = num1
            res = n + offset - num1
            start2 = 0
            end2 = min(res, num2)
    else:
        start1 = num1
        end1 = num1
        
        twoUsed = offset - num1
        start2 = min(twoUsed, num2)
        end2 = min(twoUsed + n, num2)
        
    return start1, end1, start2, end2

for line in sys.stdin:
    offset, n, num1, num2 = [int(i) for i in line.strip().split()]
    start1, end1, start2, end2 = display(offset, n, num1, num2)
    print(' '.join(map(str, [start1, end1, start2, end2])))
    

发表于 2020-08-01 23:15:56 回复(0)
import java.util.Scanner;

public class ListCompletion {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int offset = sc.nextInt();//用户已经浏览的商品数
        int n = sc.nextInt();//当前页面需要展示的商品数量
        int l1 = sc.nextInt();//列表 L1 的长度
        int l2 = sc.nextInt();//列表 L2 的长度

        int start1 = 0;
        int end1 = 0;
        int start2 = 0;
        int end2 = 0;

        if (offset > l1 + l2) {
            start1 = l1;
            end1 = l1;
            start2 = l2;
            end2 = l2;
        } else {
            if (offset >= l1) {
                start1 = l1;
                end1 = l1;
                start2 = (offset - l1);
                if (offset + n >= l1 + l2) {
                    end2 = l2;
                } else {
                    end2 = offset + n - l1;
                }
            } else {
                start1 = offset;
                if (offset + n <= l1) {
                    end1 = offset + n;
                    start2 = 0;
                    end2 = 0;
                } else {
                    end1 = l1;
                    start2 = 0;
                    end2 = offset + n - l1;
                }
            }
        }
        System.out.println(start1 + " " + end1 + " " + start2 + " " + end2);
    }

}

发表于 2020-04-09 20:41:51 回复(0)
#include <bits/stdc++.h>

using namespace std;

int main (){
    int offset,n,l1,l2;
    int x,y,z,k;
    while(cin>>offset>>n>>l1>>l2){
        
        if(offset<=l1&&n>0){
            x=(l1-offset==0?l1:offset);
            y=min(l1,offset+n);
            z=0;
            if (l2>0)
                k=max(0,offset+n-l1);
            else
                k=0;
            
        }
        if (offset>=l1&&n>0){
            x=y=l1;
            z=offset-l1;
            k=min(offset-l1+n,l2);
        }
        if (n==0){
            if(offset<=l1){
                x=y=offset;
                z=k=0;
            }
            else{
                x=y=l1;
                z=k=offset-l1;
            }
                
        }
        if (offset>l1+l2){
            x=y=l1;
            z=k=l2;
        }
            
        cout<<x<<' '<<y<<' '<<z<<' '<<k;
    }
}

发表于 2020-04-06 17:02:48 回复(0)
offset, n, l1, l2 = list(map(int, input().split()))
start1 = min(l1, offset)
end1 = min(l1, offset+n)
start2 = min(max(offset-l1,0),l2)
end2 = min(max(offset+n-l1,0),l2)
   
print(start1,end1,start2,end2)

大佬可否讲解下为什么这样做啊?
发表于 2019-09-01 14:16:18 回复(0)