找一个数组最大值算法

startstartsvip 2013-04-24 04:27:01
一个2维数组,数字有大有小,数值会有重复

假设

int[,] XY; 大小 500*500



需要追踪最大值[]以及所在位置[] 比如 99 在 200,255 和 300,100

二位数组的,某个部份会改变 比如 位置 40,200 ,长 20,宽 30 的一个区域,里面的数值 会一次改变

想在每次改变后,继续能够方便的追踪整个2维数组最大值以及所在位置

求一高效算法,提示代码都欢迎





...全文
563 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
Amos_Hong-yang 2013-05-02
  • 打赏
  • 举报
回复
把数组分成块,然后多线程解会不会好些?
bwangel 2013-04-25
  • 打赏
  • 举报
回复
从一堆数中取最大值,没有别的办法,只能挨个比较。
Kim_Du 2013-04-25
  • 打赏
  • 举报
回复
二维数组就是一维数组的集合,所以你将他看成复杂的一维数组进行处理,这样就能用一些一维数组的高效的处理方法了。
catchdream 2013-04-25
  • 打赏
  • 举报
回复
给你一个思路: 对于 500*500数据集 用 A,B两个对象: A:数据集合 50*50,则需要A[100] aList.(是否划分为更大或者更小区域则需测试) B:最大值,坐标集合。 B[100] bList.(aList与bList一一对应) B bMax:B[100]中求最大值对象(可能在 blist 中重复); 初始化: Function Init: Data->A[100] aList; 子函数for (i:0->100), 求blist; 子函数for (j:0->100), 求 bMax; 对于每次数据改变 Function DataChange: 把changeData 分为符合上面小区域的多个集合 listData:(每个listData[k] 都包含在 只有一个 aList[i] 对象中)。 改变 aList[i] 对象。 aList[i] 对象改变事件 Function AChanged(IList changedData) 判断changedData 是否覆盖 对应 bList[i]中坐标 1. 部分与未覆盖:求 max(bList[i], changedData) 2. 全部覆盖:求 max(aList[i]) 如果bList[i] 改变,重复子函数 for (j:0->100), 求 bMax;
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
引用 3 楼 zhengnan2012 的回复:
目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后的变化类似。
最大数据,可能就在 那个区域,区域里的变更可能会受到影响整个结构,最大值,次最大值
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
多谢楼上补充回复,最大值不排序的话 6 秒左右,原题 需要 对最值按 x y 坐标系排序,因为可以在每次变更的时候保持序列,也可以在需要最值位置的时候再排序,方法很多我就不在单独测试了。 PS:这是 2010 年 google code jam round 1C ,C题 Making Chess Boards 的一部分
我要坚强 2013-04-25
  • 打赏
  • 举报
回复
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication3
{
    //最大值外坐标
    class MaxItem
    {

        private int x;
        private int y;
        public MaxItem(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public int X { get { return x; } }
        public int Y { get { return y; } }

    }
    //自定义数组
    class CArry : IEnumerable<int>
    {
        private int[,] m_Arr;
        //最大值的组
        private List<MaxItem> m_MaxItems;
        private int m_MaxValue;
        private int m_X, m_Y;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x">x长度</param>
        /// <param name="y">y长度</param>
        public CArry(int x, int y)
        {
            m_Arr = new int[x, y];
            m_X = x;
            m_Y = y;
            m_MaxItems = new List<MaxItem>();
            m_MaxValue = 0;
        }
        public int XLength { get { return m_X; } }
        public int YLength { get { return m_Y; } }
        public int this[int x, int y]
        {
            get
            {

                if ((x >= m_X) || (y >= m_Y))
                    throw new IndexOutOfRangeException("索引超出了数组界限。");
                return m_Arr[x, y];
            }
            set
            {
                if ((x >= m_X) || (y >= m_Y))
                    throw new IndexOutOfRangeException("索引超出了数组界限。");
                orderByValue(x, y, value);
            }

        }
        public int MaxValue { get { return m_MaxValue; } }
        public IList<MaxItem> MaxItems()
        {
            return m_MaxItems;
        }
        //这个区间周围怎么变就怎么变
        private void orderByValue(int x, int y, int value)
        {
           
            //当前最大值比改变值要大 
            if (m_MaxValue > value)
            {
                int item = m_MaxItems.FindIndex(r => r.X == x && r.Y == y);
                if (item > -1)
                {
                    m_MaxItems.RemoveAt(item);
                }
                m_Arr[x, y] = value;
                //所有最大值都已死掉
                if (m_MaxItems.Count == 0)
                {
                    m_MaxValue = 0;
                    for (int i = 0; i < m_X; i++)
                        for (int j = 0; j < m_Y; j++)
                        {
                            if (m_MaxValue < m_Arr[i, j])
                            {
                                m_MaxItems.Clear();
                                m_MaxValue = m_Arr[i, j];
                                m_MaxItems.Add(new MaxItem(i, j));
                            }
                            else if (m_MaxValue == m_Arr[i, j])
                            {
                                m_MaxItems.Add(new MaxItem(i, j));
                            }
                        }
                }
            }
                //改变值与目前值一样
            else if (m_MaxValue == value)
            {
                m_Arr[x, y] = value;
                m_MaxItems.Add(new MaxItem(x, y));
            }
                //改变值中产生新的最大值
            else
            {
                m_MaxValue = value;
                m_MaxItems.Clear();
                m_Arr[x, y] = value;
                m_MaxItems.Add(new MaxItem(x, y));
            }
        }

        #region IEnumerable<int> 成员

        public IEnumerator<int> GetEnumerator()
        {
            foreach (var valuei in m_Arr)
            {
                yield return valuei;
            }
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
    class Program
    {
        static void Main(string[] args)
        {
            Random dr = new Random();
            int x= 500, y = 500;
            CArry arr = new CArry(x, y);
            for (int i = 0; i < x; i++)
            {
                for (int j = 0; j <y; j++)
                {

                    arr[i, j] = dr.Next(1, 100000);
                }

            }
            Console.WriteLine("初始拥有最大的项:");
            foreach (var i in arr.MaxItems())
            {
                Console.WriteLine("x:{0}y:{1}。", i.X, i.Y);

            }
            Console.WriteLine("初始最大值:{0}", arr.MaxValue);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 20; i++)
                for (int j = 0; j < 30; j++)
                {
                    arr[400 + i, 200 + j] = dr.Next(9930, 10000);
                }
            Console.WriteLine("第二次运算时间:{0}", sw.Elapsed);
            Console.WriteLine("第二次有最大的项:");
            foreach (var i in arr.MaxItems())
            {
                Console.WriteLine("x:{0}y:{1}。", i.X, i.Y);

            }

            Console.WriteLine("现在最大值:{0}", arr.MaxValue);

            Console.ReadKey();
        }

    }
}
看到是google的算法题,我又重新修改了一下,我这样的算法对吗,还是我理解错了, 存数入自定义数组=>在存入或改变的时候查看是否最大值或是最小值,免去多次循环
zhengnan2012 2013-04-25
  • 打赏
  • 举报
回复
引用 20 楼 startstartsvip 的回复:
引用 19 楼 zhengnan2012 的回复:引用 18 楼 startstartsvip 的回复:引用 17 楼 zhengnan2012 的回复:引用 6 楼 startstartsvip 的回复:引用 3 楼 zhengnan2012 的回复:目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后……
对,我错了,这样又要遍历全部了- -!
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
引用 19 楼 zhengnan2012 的回复:
引用 18 楼 startstartsvip 的回复:引用 17 楼 zhengnan2012 的回复:引用 6 楼 startstartsvip 的回复:引用 3 楼 zhengnan2012 的回复:目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后的变化类似。 最大……
3332 3343 1333 上面变成下面,找最值及位置 3332 3003 1333
zhengnan2012 2013-04-25
  • 打赏
  • 举报
回复
引用 18 楼 startstartsvip 的回复:
引用 17 楼 zhengnan2012 的回复:引用 6 楼 startstartsvip 的回复:引用 3 楼 zhengnan2012 的回复:目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后的变化类似。 最大数据,可能就在 那个区域,区域里的变更可能会受到影响整……
算了,我最终发现是我语文的问题。 到少我看楼主的发的贴子感觉我说的还能实现,但是你这两次回复我一点都没看懂。
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
引用 17 楼 zhengnan2012 的回复:
引用 6 楼 startstartsvip 的回复:引用 3 楼 zhengnan2012 的回复:目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后的变化类似。 最大数据,可能就在 那个区域,区域里的变更可能会受到影响整个结构,最大值,次最大值 是啊。如果区域内受……
区域数值变化, 1)若最大值唯一且在区域内,变化后最大值被变小了,则给出的思路是错误的
zhengnan2012 2013-04-25
  • 打赏
  • 举报
回复
引用 6 楼 startstartsvip 的回复:
引用 3 楼 zhengnan2012 的回复:目前想到的还是循环。 第一次是在初如化时处理吧。 后面是其它小区域变化,那数据很少,如果变化区域出现了比最大数据还大的,就把最大数据更新,以后的变化类似。 最大数据,可能就在 那个区域,区域里的变更可能会受到影响整个结构,最大值,次最大值
是啊。如果区域内受影响了,他存在比当前最大值还要大了,那么,刷新最大值数据就可以了。 也就是你循环的永远都是变化的那个小区域,只有初始化是才找大区域。
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
这是google 算法比赛的一道题的一小部分,我算法不太强,一天才能憋出点东西,大牛几十分钟就搞定了,有人跟我说正解 是 自建 2叉数,不过我没多想 1)每变一次就扫描一次的方法解原题需要 10分钟+ 2)这个问题的 的纠结 是 需要 通过修改过的子区域去更新全局的,的大小值 还有其位置 3)我尽量用已经有的数据结构,我用的是 SortedDictionary<int, 位置s> 建立一个 数值 到 位置的索引, 每次子区域变更,通过 原数值 与 新数值 修改 这个索引表 多谢各位回复让我感动啊!
startstartsvip 2013-04-25
  • 打赏
  • 举报
回复
引用 14 楼 dongxinxi 的回复:
引用 13 楼 dongxinxi 的回复:第一次更改之前遍历整个数组找到最大的 每次更改子块时,将当前的最大值与子块逐项比较,若子块中有新的,则更新最大值及其位置,反之只更新子块值,最大值不变 若子块中有新的最大值
子项可能修改整个结构的最大值为任意值,就是说若没有,原来的大小结构,就得从新扫表一次
  • 打赏
  • 举报
回复
引用 13 楼 dongxinxi 的回复:
第一次更改之前遍历整个数组找到最大的 每次更改子块时,将当前的最大值与子块逐项比较,若子块中有新的,则更新最大值及其位置,反之只更新子块值,最大值不变
若子块中有新的最大值
  • 打赏
  • 举报
回复
第一次更改之前遍历整个数组找到最大的 每次更改子块时,将当前的最大值与子块逐项比较,若子块中有新的,则更新最大值及其位置,反之只更新子块值,最大值不变
我要坚强 2013-04-25
  • 打赏
  • 举报
回复
 //这个区间周围怎么变就怎么变
        private void orderByValue(int x, int y, int value)
        {
            //m_MaxItems m_MaxValue这里运算   
            if (m_MaxValue > value)
            {
                int item = m_MaxItems.FindIndex(r => r.X == x && r.Y == y);
                if (item >-1)
                {
                    m_MaxItems.RemoveAt(item);
                }
                m_Arr[x, y] = value;
            }
            else if (m_MaxValue == value)
            {
                m_Arr[x, y] = value;
                int item = m_MaxItems.FindIndex(r => r.X == x && r.Y == y);               
                m_MaxItems.Add(new MaxItem(x, y));              
            }
            else
            {
                m_MaxValue = value;
                m_MaxItems.Clear();
                m_Arr[x, y] = value;
                int item = m_MaxItems.FindIndex(r => r.X == x && r.Y == y);
                 m_MaxItems.Add(new MaxItem(x, y));
               
            }
        }
我要坚强 2013-04-25
  • 打赏
  • 举报
回复
换个角度你看可以吗
   //最大值外坐标
    class MaxItem {
        
        private int x;
        private int y;
        public MaxItem(int x, int y)
        {
            this.x = x;
            this.y = y;            
        }     
        public int X { get { return x; } }
        public int Y { get { return y; } }
    
    }
    //自定义数组
    class CArry : IEnumerable<int>
    {
        private int[,] m_Arr;
        //最大值的组
        private List<MaxItem> m_MaxItems;
        private int m_MaxValue;
        private int m_X, m_Y;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="x">x长度</param>
        /// <param name="y">y长度</param>
        public CArry(int x, int y)
        {
            m_Arr = new int[x, y];
            m_X = x;
            m_Y = y;
            m_MaxItems = new List<MaxItem>();
            m_MaxValue = 0;
        }
        public int XLength { get { return m_X; } }
        public int YLength { get { return m_Y; } }
        
        public int this[int x, int y]
        {
            get
            {

                if ((x >= m_X) || (y >= m_Y))
                    throw new IndexOutOfRangeException("索引超出了数组界限。");
                return m_Arr[x, y];
            }
            set {
                if ((x >= m_X) || (y >= m_Y))
                    throw new IndexOutOfRangeException("索引超出了数组界限。");
                orderByValue(x, y, value);
            }

        }

        public IList<MaxItem> MaxItems()
        {
            return m_MaxItems;
        }
        //这个区间周围怎么变就怎么变
        private void orderByValue(int x, int y, int value)
        {
            //m_MaxItems m_MaxValue这里运算           
        }
//IEnumerable<int> 成员
nonary 2013-04-24
  • 打赏
  • 举报
回复
引用 楼主 startstartsvip 的回复:
一个2维数组,数字有大有小,数值会有重复 假设 int[,] XY; 大小 500*500 需要追踪最大值[]以及所在位置[] 比如 99 在 200,255 和 300,100 二位数组的,某个部份会改变 比如 位置 40,200 ,长 20,宽 30 的一个区域,里面的数值 会一次改变 想在每次改变后,继续能够方便的追踪……
1. 既然能改变数组,应该可以知道在哪里改变的。这个不用算法。 2. 若每次都是新数组,和旧的数组比较的话,只能循环了。一行一行的循环,用equal比较。若不相等再比较这一行。
wenbin 2013-04-24
  • 打赏
  • 举报
回复
可以把二维数组看成一个平面 对这个平面划分成M 行 N列个小的区域 每个区域保存一个最大值 根据变化区域算出 小区域变化的集合, 更新这些小区域的最大值 再找区域间的最值
加载更多回复(3)

110,477

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧