正如你对标题所理解的那样,我需要一些聪明的想法:)
我有一个List<List<Object>>
个对象。如果您将Object对象视为整数,您可以这样看:
{{1,2},{10,20,30},{100}}
我需要获得包含每个列表中一个元素的所有可能列表,即提出这个:
{{1,10,100},{1,20,100},{1,30,100},{2,10,100},{2,20,100},{2,30,100}}
当然,您在编译时不知道列表将包含多少项目,因此您不能依赖for
循环的重叠...
你怎么想出来的?时间限制与我的问题无关,因为列表可能包含很少的元素。
答案 0 :(得分:4)
迭代算法。
public class A {
public static List<List<Integer>> combinations(List<List<Integer>> inputList) {
List<List<Integer>> result = new LinkedList<List<Integer>>();
for (Integer i : inputList.get(0)) {
List<Integer> temp = new ArrayList<Integer>(1);
temp.add(i);
result.add(temp);
}
for (int i = 1; i < inputList.size(); i++) {
result = make(result, inputList.get(i));
}
return result;
}
private static List<List<Integer>> make(List<List<Integer>> in, List<Integer> n) {
List<List<Integer>> res = new LinkedList<List<Integer>>();
for (List<Integer> l : in) {
for (Integer i : n) {
List<Integer> cur = new ArrayList<Integer>(l.size() + 1);
cur.addAll(l);
cur.add(i);
res.add(cur);
}
}
return res;
}
public static void main(String[] args) {
List<List<Integer>> inputList = new ArrayList();
inputList.add(new ArrayList<Integer>() {{
add(1);
add(2);
}});
inputList.add(new ArrayList<Integer>() {{
add(10);
add(20);
add(30);
}});
inputList.add(new ArrayList<Integer>() {{
add(100);
}});
System.out.println(combinations(inputList));
}
}
*请注意,此代码不适用于制作!您应将LinkedList
替换为ArrayList
初始尺寸,进行检查等。
upd 用法示例。有一些代码改进。但它仍然只是起草。我不建议你在实际任务中使用它。
答案 1 :(得分:2)
我不会实现它,但这是一个递归算法的想法:
{{1,2,3}}
),那么结果当然是 - 每个包含一个元素的列表列表(ieeg {{1},{2},{3}}
这是原始的Python代码:
def combiner(ll):
if len(ll)==1:
return [[x] for x in ll[0]] # base case
firstlist = ll[0]
result = []
for i in combiner(ll[1:]): # recursive call
for firstelem in firstlist:
result.append([firstelem]+i) # combining lists
return result
答案 2 :(得分:1)
为了完整起见,您所搜索的内容称为列表的笛卡尔积,因为我们的结果列表的大小是各个列表大小的乘积。
编辑:这是一个适用于Iterables的任意Iterables的实现,并创建一个Iterable列表。它会在迭代时懒洋洋地创建元素,因此它适用于非常适合内存的大型产品。
package de.fencing_game.paul.examples;
import java.util.*;
/**
* A iterable over the cartesian product of a iterable of iterables
* with some common element type.
*<p>
* The elements of the product are tuples (lists) of elements, one of
* each of the original iterables.
*<p>
* The iterator iterates the elements in lexicographic order, ordered by
* the appearance of their components in their respective iterators.
*<p>
* Since we are iterating the iterables lazily, the iterators should
* act the same each time, otherwise you'll get strange results (but it
* will still be well-defined).
*</p>
*
* Inspired by the question <a href="http://stackoverflow.com/questions/5220701/how-to-get-a-list-of-all-lists-containing-exactly-one-element-of-each-list-of-a-l/5222370#5222370">How to get a list of all lists containing exactly one element of each list of a list of lists</a> on Stackoverflow (by Dunaril).
*
* @author Paŭlo Ebermann
*/
public class ProductIterable<X>
implements Iterable<List<X>>
{
private Iterable<? extends Iterable<? extends X>> factors;
public ProductIterable(Iterable<? extends Iterable<? extends X>> factors) {
this.factors = factors;
}
public Iterator<List<X>> iterator() {
return new ProductIterator();
}
private class ProductIterator
implements Iterator<List<X>>
{
/**
* an element of our stack, which contains
* an iterator, the last element returned by
* this iterator, and the Iterable which created
* this iterator.
*/
private class StackElement {
X item;
Iterator<? extends X> iterator;
Iterable<? extends X> factor;
boolean has;
StackElement(Iterable<? extends X> fac) {
this.factor = fac;
newIterator();
}
/**
* checks whether the {@link #step} call can
* get a new item.
*
*/
boolean hasNext() {
return has ||
(has = iterator.hasNext());
}
/**
* steps to the next item.
*/
void step() {
item = iterator.next();
has = false;
}
/**
* creates a new iterator.
*/
void newIterator() {
iterator = factor.iterator();
has = false;
}
/**
* for debugging: a string view of this StackElement.
*/
public String toString() {
return "SE[ i: " + item + ", f: " + factor + "]";
}
}
/**
* our stack of iterators to run through
*/
private Deque<StackElement> stack;
/**
* is our next element already produced (= contained in
* the `item`s of the stack?
*/
private boolean hasNext;
/**
* constructor.
*/
ProductIterator() {
stack = new ArrayDeque<StackElement>();
try {
fillStack();
hasNext = true;
}
catch(NoSuchElementException ex) {
hasNext = false;
}
}
/**
* creates the stack. only called from constructor.
*/
private void fillStack() {
for(Iterable<? extends X> fac : factors) {
StackElement el = new StackElement(fac);
el.step();
stack.push(el);
}
}
/**
* steps the iterator on top of the stack, and maybe the iterators
* below, too.
* @return true if more elements are available.
*/
private boolean stepIterator() {
if(stack.isEmpty())
return false;
StackElement top = stack.peek();
while(!top.hasNext()) {
stack.pop();
if (!stepIterator()) {
return false;
}
top.newIterator();
stack.push(top);
}
top.step();
return true;
}
/**
* returns true if `next` will return a next element.
*/
public boolean hasNext() {
return
hasNext ||
(hasNext = stepIterator());
}
/**
* returns the next element of the cartesian product.
*/
public List<X> next() {
if(!hasNext()) {
throw new NoSuchElementException();
}
hasNext = false;
return makeList();
}
/**
* creates a list from the StackElements in reverse order.
*/
private List<X> makeList() {
List<X> list = new ArrayList<X>(stack.size());
// TODO: more efficient reverse copying
for(StackElement se : stack) {
list.add(0, se.item);
}
return list;
}
/**
* the remove method is not supported,
* the cartesian product is immutable.
*/
public void remove() {
throw new UnsupportedOperationException();
}
} // class ProductIterator
/**
* a test method which creates a list of lists and
* from this the cartesian product.
*/
public static void main(String[] params) {
@SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30),
Arrays.asList(100));
Iterable<List<Integer>> product =
new ProductIterable<Integer>(factors);
List<List<Integer>> productList =
new ArrayList<List<Integer>>();
for(List<Integer> pEl : product) {
productList.add(pEl);
System.out.println(pEl);
}
System.out.println(productList);
}
}
还有一个编辑:这是一个基于索引的惰性列表实现。
package de.fencing_game.paul.examples;
import java.util.*;
/**
* The cartesian product of lists, in an (unmodifiable) index-based
* implementation.
*
*<p>
* The elements of the product are tuples (lists) of elements, one from
* each of the base list's element lists.
* These are ordered in lexicographic order, by their appearance in the
* base lists.
*</p>
*<p>
* This class works lazily, creating the elements of the product only
* on demand. It needs no additional memory to the base list.
*</p>
*<p>
* This class works even after changes of the base list or its elements -
* the size of this list changes if any of the factor lists changes size.
* Such changes should not occur during calls to this method, or
* you'll get inconsistent results.
*</p>
* <p>
* The product of the sizes of the component lists should be smaller than
* Integer.MAX_INT, otherwise you'll get strange behaviour.
* </p>
*
*<p>
* Inspired by the question <a href="http://stackoverflow.com/questions/5220701/how-to-get-a-list-of-all-lists-containing-exactly-one-element-of-each-list-of-a-l/5222370#5222370">How to get a list of all lists containing exactly one element of each list of a list of lists</a> on Stackoverflow (by Dunaril).
*
* @author Paŭlo Ebermann
*/
public class ProductList<X>
extends AbstractList<List<X>>
{
private List<? extends List<? extends X>> factors;
/**
* create a new product list, based on the given list of factors.
*/
public ProductList(List<? extends List<? extends X>> factors) {
this.factors = factors;
}
/**
* calculates the total size of this list.
* This method takes O(# factors) time.
*/
public int size() {
int product = 1;
for(List<?> l : factors) {
product *= l.size();
}
return product;
}
/**
* returns an element of the product list by index.
*
* This method calls the get method of each list,
* so needs needs O(#factors) time if the individual
* list's get methods are in O(1).
* The space complexity is O(#factors), since we have to store
* the result somewhere.
*
* @return the element at the given index.
* The resulting list is of fixed-length and after return independent
* of this product list. (You may freely modify it like an array.)
*/
public List<X> get(int index) {
if(index < 0)
throw new IndexOutOfBoundsException("index " + index+ " < 0");
// we can't create a generic X[], so we take an Object[]
// here and wrap it later in Arrays.asList().
Object[] array = new Object[factors.size()];
// we iteratively lookup the components, using
// modulo and division to calculate the right
// indexes.
for(int i = factors.size() - 1; i >= 0; i--) {
List<?> subList = factors.get(i);
int subIndex = index % subList.size();
array[i] = subList.get(subIndex);
index = index / subList.size();
}
if(index > 0)
throw new IndexOutOfBoundsException("too large index");
@SuppressWarnings("unchecked")
List<X> list = (List<X>)Arrays.asList(array);
return list;
}
/**
* an optimized indexOf() implementation, runs in
* O(sum n_i) instead of O(prod n_i)
* (if the individual indexOf() calls take O(n_i) time).
*
* Runs in O(1) space.
*/
public int indexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.indexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized lastIndexOf() implementation, runs in
* O(sum n_i) time instead of O(prod n_i) time
* (if the individual indexOf() calls take O(n_i) time).
* Runs in O(1) space.
*/
public int lastIndexOf(Object o)
{
if(!(o instanceof List))
return -1;
List<?> list = (List<?>)o;
if (list.size() != factors.size())
return -1;
int index = 0;
for(int i = 0; i < factors.size(); i++) {
List<?> subList = factors.get(i);
Object candidate = list.get(i);
int subIndex = subList.lastIndexOf(candidate);
if(subIndex < 0)
return -1;
index = index * subList.size() + subIndex;
}
return index;
}
/**
* an optimized contains check, based on {@link #indexOf}.
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* a test method which creates a list of lists and
* shows the cartesian product of this.
*/
public static void main(String[] params) {
@SuppressWarnings("unchecked")
List<List<Integer>> factors =
Arrays.asList(Arrays.asList(1,2),
Arrays.asList(10,20,30, 20),
Arrays.asList(100));
System.out.println("factors: " + factors);
List<List<Integer>> product =
new ProductList<Integer>(factors);
System.out.println("product: " + product);
List<Integer> example = Arrays.asList(2,20,100);
System.out.println("indexOf(" + example +") = " +
product.indexOf(example));
System.out.println("lastIndexOf(" + example +") = " +
product.lastIndexOf(example));
}
}
我添加了contains,indexOf和lastIndexOf的实现,它们比AbstractList(或AbstractCollection)中的原始实现要好得多(至少比你的例子中更大的因素)。这些没有针对子列表进行优化,因为子列表只是从AbstractList中获取。
答案 3 :(得分:0)
简单的迭代算法。
public static List<List<Object>> doStaff(List<List<Object>> objectList) {
List<List<Object>> retList = new ArrayList<List<Object>>();
int[] positions = new int[objectList.size()];
Arrays.fill(positions,0);
int idx = objectList.size() -1;
int size = idx;
boolean cont = idx > -1;
while(cont) {
idx = objectList.size() -1;
while(cont && positions[idx] == objectList.get(idx).size()) {
positions[idx] = 0;
idx--;
if(idx > -1) {
positions[idx] = positions[idx]+ 1;
} else {
cont = false;
}
}
if(cont) {
List<Object> tmp = new ArrayList<Object>(size);
for(int t = 0; t < objectList.size(); t++) {
tmp.add(t, objectList.get(t).get(positions[t]));
//System.out.print(objectList.get(t).get(positions[t])+ " ");
}
retList.add(tmp);
// System.out.println();
positions[size] = positions[size] + 1;
}
}
return retList;
}
如果有必要,请解释,请告诉我。
答案 4 :(得分:0)
您可以使用该scala代码:
def xproduct (xx: List [List[_]]) : List [List[_]] =
xx match {
case aa :: bb :: Nil =>
aa.map (a => bb.map (b => List (a, b))).flatten
case aa :: bb :: cc =>
xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten
case _ => xx
}
由于crossproduct是笛卡儿产品的另一个名称,因此它的名称是xproduct。
答案 5 :(得分:0)
这是phimuemue的Python算法的java实现。
private static List<List<Item>> getAllPossibleLists(List<List<Item>> itemsLists) {
List<List<Item>> returned = new ArrayList<List<Item>>();
if(itemsLists.size() == 1){
for (Item item : itemsLists.get(0)) {
List<Item> list = new ArrayList<Item>();
list.add(item);
returned.add(list);
}
return returned;
}
List<Item> firstList = itemsLists.get(0);
for (List<Item> possibleList : getAllPossibleLists(itemsLists.subList(1, itemsLists.size()))) {
for(Item firstItem : firstList){
List<Item> addedList = new ArrayList<Item>();
addedList.add(firstItem);
addedList.addAll(possibleList);
returned.add(addedList);
}
}
return returned;
}
欢迎进一步发表评论。感谢您的所有努力!