【回溯】C058_NK_牛牛的三角形(选数 / 二分 + 滑动窗口)

一、Problem

牛牛有一个数组长度大小为 n,数组中有 n 个正整数。现在牛牛请你从其中选出三个元素(注意选择元素的下标不能相同,但是其值可以相同)组成一个三角形。

无法做到,请输出一行一个字符串 “No solution”,反之请输出这三个元素的值。

如果有多种组成三角形的元素组合,你可以输出任意一种

输入描述:

第一行是一个正整数 n , ( 3 ≤ n ≤ 1 0 2 ) n,(3\leq n \leq 10^2) n,(3n102) 表示数组的元素个数。

接下来一行输入n个正整数 a i a_i ai 表示每个数组元素的值。

输出描述:

如无法做到,请输出一行一个字符串 “No solution”,反之请输出这三个元素的值。

如果有多种组成三角形的元素组合,你可以输出任意一种。

5
2 2 3 2 2

2 2 3

二、Solution

方法一:dfs

放弃 3 层循环的我,选择了这种做法:选够了就检查是否可以组成三角形…

三层循环的做法:

for (i, i, n)
for (j, i+1, n)
for (k, j+1, n) {
	if(a + b > c && a + c > b && b + c > a)
		print(...)
}
import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static class Solution {
        int n, a[];
        boolean done;
        List<Integer> all = new ArrayList<>(3), res;
        
        boolean check() {
            int a = all.get(0), b = all.get(1), c = all.get(2);
            if (a+b <= c || a + c <= b || b + c <= a) return false;
            if (a-b >= c || a - c >= b || b - c >= a) return false;
            return true;
        }
        void dfs(int idx) {
            if (done)  return;
            if (all.size() == 3) {
                if (check()) {
                    done = true;
                    res = new ArrayList(all);                    
                }
                return;
            }
            for (int i = idx; i < n; i++) {
                all.add(a[i]);
                dfs(i+1);
                all.remove(all.size()-1);
            }
        }
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
            n = sc.nextInt();
            a = new int[n];
            for (int i = 0; i < n; i++) 
            	a[i] = sc.nextInt();
            dfs(0);
            if (res == null) System.out.println("No solution");
            else for (int i = 0; i < res.size(); i++)
                System.out.print(res.get(i) + " ");
        }
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度: O ( . . . ) O(...) O(...)
  • 空间复杂度: O ( . . . ) O(...) O(...)

方法二:二分 + 滑动窗口

… 不多说,类似题

import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static class Solution {
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
            int n = sc.nextInt(), a[] = new int[n], cnt = 0;
            for (int i = 0; i < n; i++) a[i] = sc.nextInt();
            Arrays.sort(a);
            
            a: for (int i = n -1; i >= 2; i--) {
                int l = 0, r = i - 1;
                while (l < r) {
                    if (a[l] + a[r] > a[i]) {
                        System.out.printf("%d %d %d", a[l], a[r], a[i]);
                        cnt += r - l;
                        r--;
                        break a;
                    } else {
                        l++;
                    }
                }
            }
            if (cnt == 0) System.out.println( "No solution");
        }
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

你可能感兴趣的:(#,【回溯】,#,二分搜索,#,【滑动窗口】)