[Recursion + Backtracking] Realize the combination, arrangement and full arrangement of array elements

table of Contents

One, the combination of array elements

Second, the full arrangement of array elements

Third, the permutation and combination of array elements

Hello, how are you, I am the little gray ape! A super programmer who can write bugs!

Recently, when doing blue bridge cup related test questions, I found that the use of permutation and combination of array elements is very extensive, and common permutation and combination types of questions are also typical examples of data structures and algorithms, so today I will share with you today. In the usual development process, several types and solutions of permutations and combinations are often used:

One, the combination of array elements

For the case of taking out m numbers from the n-element array arr (regardless of order and no repetition) and placing them in the new array newarr, the common idea is to use the recursive idea:

  1. Take n numbers from the array arr, then we can take the first number of arr as the first element of newarr
  2. After taking out the first element of arr, take out m-1 elements from the following n-1 elements, (this is the sub-problem of the first step) using recursive implementation.
  3. When 0 elements need to be taken out, a combined task is completed
  4. Go back to the first step, use the for loop to take out the second element (start the next combination), and loop nm times in total.

The specific implementation can be viewed in the following function, which can be directly called and used:

    /**
	 * 在数组中选取n个数进行组合(不考虑顺序且数据不重复)
	 * @param 待处理的数组
	 * @param newarr 组合后得到的数组
	 * @param k  从哪一个下标的元素开始取
	 * @param n 需要取出元素的个数
	 * */
	private static void combination(int[] arr,int[] newarr, int k,int n) {
		//当需要取出的元素个数是0时,说明组合完成
		if (n==0) {
			for (int i = 0; i < newarr.length; i++) {
				System.out.print(newarr[i]);
			}
			System.out.println();
			return;
		}
		for (int i = k; i <= arr.length-n; i++) {		
			newarr[newarr.length-n] = arr[i];	//将提取出来的数依次放到新数组中
			combination(arr, newarr,i+1, n-1);	//按照同样的方法从剩下的元素中选出n-1个元素
		}
	}

Test case:

public static void main(String[] args) {
		int[] arr = {1,2,3,4};		//待处理的数组
		int n = 3;	//取出元素的个数
		int[] newarr = new int[n];		//存放结果的数组
		combination(arr, newarr, 0, n);
	}

Second, the full arrangement of array elements

For the full arrangement of the array arr with n numbers, the idea used is recursion plus backtracking.

  1. Fully arrange the n elements, interchange the first element with the following elements in turn, and determine the first element
  2. Full arrangement of the following n-1 elements (can be regarded as the sub-problem of the first step) is implemented by recursion
  3. Replace the exchanged elements back to prevent the order of the array elements from being disrupted (backtracking thought)

The specific implementation can see the following function, (can be used directly)

    /**
	 * 对数组中所有的元素进行全排列
	 * @param arr 待排列的数组
	 * @param k 确定第几个元素,是下标,从0开始
	 * */
	private static void f(int[] arr, int k) {
		//当k等于数组的长度时,说明排列完成
		if (k == arr.length) {
			//将排列好的数组输出
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i]);
			}
			System.out.println();
		}
		
		for (int i = k; i < arr.length; i++) {
			//将待确定的元素位置和后面的元素互换
			int t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
			
			//递归(确定第k+1个元素)
			f(arr, k+1);
			
			//回溯,将调换后的元素重新调换回来
			t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
		}	
	}

Test case:

public static void main(String[] args) {
		int[] arr = {1,2,3,4};		//待处理的数组
		int n = 3;	//取出元素的个数
		int[] newarr = new int[n];		//存放结果的数组
		f(arr, 0);
	}

Third, the permutation and combination of array elements

With the above understanding of taking out m numbers from the n-element array arr (regardless of order and no repetition) and fully permuting n numbers, then taking out m numbers from n numbers to achieve permutation The problem can be seen as a combination of the above two problems.

According to the idea of ​​mathematics, we can first select m elements from an array of n elements, and then arrange all the m elements.

The method of implementation is as follows:

    /**
	 * 数组中对n个数进行全排列
	 * @param 待处理的数组
	 * @param newarr 排列后得到的数组
	 * @param k  从哪一个下标的元素开始处理
	 * @param n 处理元素的个数
	 * */
	private static void pac(int[] arr,int[] newarr, int k,int n) {
		//当n=0时,说明选取的数的个数为0,也就是组合完成
		if (n==0) {
			f(newarr, 0);	//对组合到的新数组进行全排列
			return;
		}
		for (int i = k; i <= arr.length-n; i++) {		
			newarr[newarr.length-n] = arr[i];
			pac(arr, newarr,i+1, n-1);
		}
	}
	
	/**
	 * 对数组中所有的元素进行全排列
	 * @param arr 待排列的数组
	 * @param k 确定第几个元素,是下标,从0开始
	 * */
	private static void f(int[] arr, int k) {
		//当k等于数组的长度时,说明排列完成
		if (k == arr.length) {
			//将排列好的数组输出
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i]);
			}
			System.out.println();
		}
		
		for (int i = k; i < arr.length; i++) {
			//将待确定的元素位置和后面的元素互换
			int t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
			
			//递归(确定第k+1个元素)
			f(arr, k+1);
			
			//回溯,将调换后的元素重新调换回来
			t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
		}	
	}

Test case:

public static void main(String[] args) {
		int[] arr = {1,2,3,4};		//待处理的数组
		int n = 3;	//取出元素的个数
		int[] newarr = new int[n];		//存放结果的数组
		pac(arr,newarr,0, n);
	}

The above are the three common types of permutations and combinations and their solutions. The main idea is to use recursion and backtracking. There are optimizations or deficiencies in it, and I hope you can make corrections.

Feel good, remember to like and follow!

Little Gray Ape will accompany you to make progress together!

Guess you like

Origin blog.csdn.net/weixin_44985880/article/details/113434593