用4个for把所有可能性都试一遍。
解决方案 »
- Java新手向各位求助 对话框的问题
- jboss4.0.3sp1的request的参数取值乱码,当使用get方式传递
- 请问SimpleDateFormat问题,对日期format后生成字符串,在对此字符串format就出错,不知道为什么?
- 大家近来说说JAVA开源的几个有代表性的网站或者是项目吧~~~不要很大~~一般人都能看懂~~但要有用~~来者有分~~
- 用java实现ping命令可否?直接写还是用其他语句 ,谢谢各位老大啦!挺着急的,呵呵
- 各位,给个建议给我!
- 哪里有《21天学Java》电子版图书,100分送上
- 谁能贴个JBuilder 或者 JAVA写的 MDI的例子?多谢~
- Patrick_DK请进
- 哪位仁兄研究过 jndi_turorial 进来帮帮忙好吗?
- 使用Digester能否将数据保存到一个xml文件?
- 请教一个问题
比如A=100,队列中如下:1,2,...37,89,98,99等,将1,2,等较小的(既i*4也<100)分为一类,将98,99等较大的分为另一类(既i*4也>>100),可以跳过选取89,98,99,87这样的组合,能减少部分工作量,至于如何分组看楼主的意思了,这个分组法还不是很成熟。
<<
for( ... )
for ( ... )
for ( ... )
for ( ... )
>>
但是楼主的条件是又不允许重复,所以还需要加上很多判断的临时标示变量。另外,如果变化数目,修改量也是很大,语句就变得很复杂。所以,俺们可以看看有没有更好的办法来做这些遍历。
换一个思路这么看,这一系列数据(100个),可以看作一个聚集来处理。需要做的就是使用迭代来遍历所有的数据,而且可能需要多次迭代(需要2个数就迭代2次,需要3个数就迭代3次,类推),这样,无论需要多少个数,只要多次迭代嵌套就可以了。问题在于,如何在一次迭代的时候避免其他的迭代当前正在处理的INDEX(避免重复)。于是,俺们可以考虑增加一个迭代的缓存来实现这点重复的剔除。俺做了这么一个聚集的简单实现如下:
<<
final class NumberCollections {
private final Map iteratorBuffer = new HashMap();
private final BigDecimal[] nums; public NumberCollections(BigDecimal[] nums) {
if(nums==null) throw new NullPointerException();
this.nums = new BigDecimal[nums.length];
System.arraycopy(nums, 0, this.nums, 0, nums.length);
} public Iterator iterator() {
Iterator it = new DefaultIterator();
iteratorBuffer.put(it, new Integer(0));
return it;
} // private :
private boolean isIndexInBuffer(Iterator thisIt, int index) {
for(Iterator it=iteratorBuffer.keySet().iterator();it.hasNext();) {
Iterator each = (Iterator)it.next();
if(each==thisIt) continue;
Integer eachIndex = (Integer)iteratorBuffer.get(each);
if(eachIndex.intValue()==index) return true;
}
return false;
}
private void updateBuffer(Iterator it, int currentIndex) {
if(!iteratorBuffer.containsKey(it)) return;
iteratorBuffer.put(it, new Integer(currentIndex));
}
private void removeBuffer(Iterator it) {
iteratorBuffer.remove(it);
} private class DefaultIterator implements Iterator {
private int index = 0;
public boolean hasNext() {
if(index==nums.length) {
removeBuffer(this);
return false;
}
for(int i=index;i<nums.length;i++) {
if(!isIndexInBuffer(this, i)) return true;
}
removeBuffer(this);
return false;
} public Object next() {
for(int i=index;i<nums.length;i++) {
if(!isIndexInBuffer(this, i)) {
updateBuffer(this, i);
index = i+1;
return nums[i];
}
}
return null;
} public void remove() {
throw new UnsupportedOperationException();
}
}
}
>>
由于楼主的数据允许整型和浮点,所以使用BigDecimal来处理之。关键在于DefaultIterator这个迭代的实现类和iteratorBuffer的交互处。程序写的比较仓促。:)
在这样的聚集的前提之前,客户端就可以不用处理迭代的逻辑了,只需要简单的嵌套进行迭代即可(应该还有更好的方式来处理)。
简单的例子如下:
<<
NumberCollections nc = new NumberCollections(nums);
for(Iterator it1=nc.iterator(); it1.hasNext(); ) {
BigDecimal n1 = (BigDecimal)it1.next();
for(Iterator it2=nc.iterator(); it2.hasNext(); ) {
BigDecimal n2 = (BigDecimal)it2.next();
for(Iterator it3=nc.iterator(); it3.hasNext(); ) {
BigDecimal n3 = (BigDecimal)it3.next();
for(Iterator it4=nc.iterator(); it4.hasNext(); ) {
BigDecimal n4 = (BigDecimal)it4.next(); if(validate(n1,n2,n3,n4)) {...}
}
}
}
}
>>
只需要实现validate方法来验证是否是需要的组合就可以了。
BTW,如果数据量很大,这样的算法一定效率非常低下,并不推荐采用。
首先对100个数字进行排序
然后分4组
初步设定个组的边界值为 0,25,75,100
(如果100个数里有这几个值正好,没有也无所谓,最后去掉包含这4个数的组合就是)这样,我们可以得到4组数据
0~25,26~50,51~75,76~100
A B C D
下面可以通过简单的分析得到一些规律
2A+2B=100
2A+C=100
A+C=100
2A+D=100
(也许还有,数字的意思是从该区域取多少个)
由于我们要求是4个数字相加,且不重复这样,可能的取法
2A+2B
(呵呵,好像就这么一种吧)嗯,思路是这样的,算是抛砖引玉吧
^_^
3A+C
3A+D
这下应该没有了
一,排序
二,找到比A大的位置
三,选择,从找到的位置往小的方向选择4个数,如果和为A。ok。最后找完为止。
假设数据存放在Array中,
for(int i=0;i<Array.length;++i){
for(int j=0;j<Array.length;++j){
if(i==j) break;
for(int k=0;k<Array.length;++k){
if((k==i)||(k==j)) break;
for(int n=0;l<Array.length;++l){
if((n==i)||(n==j)||(n==k)) break;
if((Array[i]+Array[j]+Array[k]+Array[n])==result)
....相关处理
}
}
}
}如果要提高效率,最好先进行排序,向楼上几位提的。防止计算向四个大于50的数的相加。
然后,俺们可以剔除无解的情况?两种无解:
(1) 最小的连续4个数相加大于A无解;
(2) 最大的连续4个数相加小于A无解;接下来,俺们可以把A线段提出来,A线段多大?从最小数点到A点的距离即为A线段的长度。
然后,把A线段平均切分为4段,记为S1, S2, S3和S4。然后把数轴上所有数列中的数放入到相应的4段中(在这一步就可能可以剔除很多无用的数据了)
下面要做的事情,就是按照“silverswords(笨笨虫冲)”推出的公式进行遍历计算,得到所有可能得到A的值,比如 3S1 + S3 = A; 3S1 + S4 = A; 2S1 + 2S2 = A。如果算法修改成这样,确实效率会得到很大的改善。
取数的思路是:首先4个数中必有A类,其次D类的数最多1个,C类的数最多2个,B类的数最多3个,而A类的数最多为3个,而取数与顺序无关。
所以可以规定第一个数必须为A类,第二个数可以任选A,B,C,D类,第三个数可以根据思路排除一些不可能的选取法,第四种一般可以根据前3个数的类型唯一确定它的类型。