逻辑 - 需要找到重叠的数字范围

Posted

技术标签:

【中文标题】逻辑 - 需要找到重叠的数字范围【英文标题】:Logic - Need to find overlapping ranges of numbers 【发布时间】:2013-03-14 09:55:31 【问题描述】:

假设我有一个带有“startNo”整数和“endNo”整数的“数字”对象数组。

数组中可以有多个“数字”,我想获得一个带有修改对象的新数组,该数组只有没有重叠的范围。

例如:如果数组有:

number
( startNo:1 endNo:3)
( startNo:1 endNo:7)
( startNo:2 endNo:9)
( startNo:15 endNo:18)
( startNo:50 endNo:60)
( startNo:55 endNo:65)

我想得到一个这样的数组:

number
( startNo:1 endNo:9)
( startNo:15 endNo:18)
( startNo:50 endNo:65)

我一直在尝试使用 structs、fors 和其他所有方法尝试不同的方法,但我得到的只是多层次的混淆。

如果有帮助,我正在开发 Objective-C 平台

补充:startPage可以是大数,endPage可以是小数。

【问题讨论】:

【参考方案1】:

这是一道经典的算法课题..

按第一个(最小)值的降序对数组进行排序。 跟踪两个变量:开始段,结束段。

每回合选择一个数组并检查开始和结束的数字,并确定它是否 是否在该段中。

这样可以找到重叠的地方

祝你好运

【讨论】:

感谢您的回复。我无法“跟踪两个变量” 正如上面其他人提到的,这只是段/数组的边界。 请查看修改后的问题。 解决方法应该是一样的,对数组进行排序并按顺序挑选(从最大开始编号到最小)。【参考方案2】:

假设你的班级是 MyNumbers 并且是这样的:

@interface MyNumbers : NSObject
@property NSInteger startNumber;
@property NSInteger endNumber;

- (id)initWithStartNumber:(NSInteger)start withEnd:(NSInteger)end;

@end

以及合并的方式:

- (void)yourMethod

    MyNumbers *obj1=[[MyNumbers alloc]initWithStartNumber:1 withEnd:3];
    MyNumbers *obj2=[[MyNumbers alloc]initWithStartNumber:1 withEnd:7];
    MyNumbers *obj3=[[MyNumbers alloc]initWithStartNumber:2 withEnd:9];
    MyNumbers *obj4=[[MyNumbers alloc]initWithStartNumber:15 withEnd:18];
    MyNumbers *obj5=[[MyNumbers alloc]initWithStartNumber:50 withEnd:60];
    MyNumbers *obj6=[[MyNumbers alloc]initWithStartNumber:55 withEnd:65];

    NSArray *array=@[obj1,obj2,obj3,obj4,obj5,obj6];
    NSMutableArray *mergedArray=[NSMutableArray arrayWithObject:array[0]];

    for (NSInteger index=1; index<array.count; index++) 
        MyNumbers *currentNumber=array[index];
        MyNumbers *previousNumber=array[index-1];

        if (currentNumber.startNumber<=previousNumber.endNumber) 
            previousNumber.endNumber=currentNumber.endNumber;
            [mergedArray replaceObjectAtIndex:mergedArray.count-1 withObject:previousNumber];
        
        else
            [mergedArray addObject:currentNumber];
        
    

    for(MyNumbers *element in mergedArray)
        NSLog(@"startNo:%d endNo:%d",element.startNumber, element.endNumber);
     

输出:

2013-03-14 17:14:05.040 继承[34234:303] startNo:1 endNo:9 2013-03-14 17:14:05.041 继承[34234:303] startNo:15 endNo:18 2013-03-14 17:14:05.041 继承[34234:303] startNo:50 endNo:65

【讨论】:

很好的答案 Anoop。感谢您的代码。在我的某些情况下,另一个答案处理了数字不是递增顺序并且起始编号大于结束编号的情况。仍然感谢您的回答。非常感激。 :) 我根据你的问题解决了。如果您说过,在未排序的情况下,Obj-C 中只需要一行额外的语句。而你标记为 obj-c。不是 C#。无论如何,由您决定哪个是最好的,什么是您感觉最好的。 我猜你是对的。请添加该行代码以进行存档,我会将您的答案标记为已接受。另请注意,还有一个漏洞,如果一个数字范围位于现有单位范围之间(例如:5-10 和 2-14),那么它可能会失败。虽然我还没有让它在机器上运行.再次感谢您的帮助。【参考方案3】:

只是快速的想法未经测试:

1.获取最小的起始编号say sn和对应的end no say en。

2.如果 start no 小于 sn 则继续检查下一个对象,然后忽略 start no 。如果结束编号大于 en 则将新的结束编号存储到您的 en 中。

3.这会给你你的对象。

4.如果起始编号大于en,则创建一个新对象添加到数组中。

这应该可以。如果您还有其他问题,请告诉我

【讨论】:

请看修改后的问题【参考方案4】:

解决这个问题的简单方法:

    创建一个新的空数组(我们将其命名为:tmp)。 将第一个数组的 startNoendNo 放入 tmp。 获取第二个数组的 startNoendNo。然后,决定它们是否与 tmp 中的重叠。 (如果它们不重叠,则将它们都插入到 tmp 的末尾。) 对每个数组重复这些步骤。 tmp 现在将保存所有范围,没有重叠。

【讨论】:

请查看修改后的问题。 你只需要弄清楚如何决定它们是否重叠。想想可能发生的情况。 感谢您的回复。非常感谢。【参考方案5】:

//它是用C#语言编写的。但是概念可以用任何编程语言来实现。

public class Range

    public int startNo  get; set; 
    public int stopNo  get; set; 

    public Range(int start, int stop)
    
        startNo = start;
        stopNo = stop;
    


        public void GetUniqueRanges()
    
        var rangeList = new List<Range>();
        rangeList.Add(new Range(7,4));
        rangeList.Add(new Range(3, 15));
        rangeList.Add(new Range(54, 35));
        rangeList.Add(new Range(45, 60));
        rangeList.Add(new Range(60,75));
        rangeList.Add(new Range(76,100));
        rangeList.Add(new Range(6,10));
        rangeList.Add(new Range(16,24));
        rangeList.Add(new Range(19,34));

        var sorted = new List<Range>();
        foreach (var range in rangeList)
        
            var item = new Range(Math.Min(range.startNo, range.stopNo), Math.Max(range.startNo, range.stopNo));
            sorted.Add(item);
        
        var result = new List<Range>();
        sorted = sorted.OrderBy(x => x.startNo).ToList();
        var counter = sorted.Count;
        for (var i = 0; i < counter; )
        
            var item = new Range (sorted[i].startNo, sorted[i].stopNo );
            var j = i + 1;
            for (; j < counter; j++)
            
                if (sorted[j].startNo <= item.stopNo)
                
                    item.stopNo =Math.Max(item.stopNo, sorted[j].stopNo);
                
                else
                

                    break;
                
            
            i = j;
            result.Add(item);
        
    

【讨论】:

它是在目标 c 中而不是在 java 或 c# 中。 NSFeaster 无法将 c# API 转换为目标 c。 嗨维杰,非常感谢。虽然这是 C#,但我明白其中的逻辑。这个解决方案是最紧凑的,并且循环次数更少,所以我会接受这个答案是正确的。

以上是关于逻辑 - 需要找到重叠的数字范围的主要内容,如果未能解决你的问题,请参考以下文章

如何比较重复的列,每个列都有一个数字范围,如果它们的数字范围相互重叠,则返回错误?

PL/SQL:在由开始和结束定义的重叠日期范围内查找孤岛

范围查询 ~ VB

数字问题-LeetCode 435436441442443445448(数字)

给定 2 个整数列表如何找到不重叠的范围?

IP 地址重叠/在 CIDR 范围内