分解单位数

形如:1/a 的分数称为单位分数。

可以把1分解为若干个互不相同的单位分数之和。
例如:
1 = 1/2 + 1/3 + 1/9 + 1/18
1 = 1/2 + 1/3 + 1/10 + 1/15
1 = 1/3 + 1/5 + 1/7 + 1/9 + 1/11 + 1/15 + 1/35 + 1/45 + 1/231
等等,类似这样的分解无穷无尽。

我们增加一个约束条件:最大的分母必须不超过30

请你求出分解为n项时的所有不同分解法。

数据格式要求:

输入一个整数n,表示要分解为n项(n<12)

#include<stdio.h>
#include<stdlib.h>
void dwfs(int a[], int n, int qishi, int ctrl) {
    int i;
    if(n == ctrl) {
        int sum = 1, sum2 = 0;
        for(i = 0; i < n; i++)
        sum *= a[i];
        for(i = 0; i < n; i++)
        sum2 += sum/a[i];
        if(sum == sum2) {
            for(i = 0; i < n; i++)
            printf("1/%d ", a[i]);
            printf("\n");
        }
        return;
    }
    for(i = qishi; i < 30; i++) {
           a[ctrl] = i;
           dwfs(a, n, i+1, ctrl+1);
       }
}
int main() {
    int i, n, *pa;
    scanf("%d", &n);
    pa = (int*)calloc(n, sizeof(int));
    dwfs(pa, n, 2, 0);
    return 0;
}
//递归全排列1~30之间的四各组合的分母,计算他们的倒数和是否为1,是,则输出
import java.util.Scanner;

public class Main {
	static int n;//要分解为n项(n<12)
	
	public static void main(String[] args) {
		@SuppressWarnings("resource")
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		int[] num=new int[n];
		cmp(0,num,2);//调用方法
	}
	//自定义方法
	private static void cmp(int fm, int[] num, int sum) {
	//fm=记录项数量,num=保存项(遍历得到分母),sum=每次递归遍历起始分母
		if(fm==n) {//满足项数量
			int z=1;//分子
			int m=num[0];//分母
			for(int i=1;i<n;i++) {
				//验证求和(分母全部相乘,求分子是否=分母)即,和为1
				z=z*num[i]+m;//分子和
				m=m*num[i];//分母和
			}
			if(z==m) {//和为1
				for(int i=0;i<n;i++) {
					System.out.print("1/"+num[i]+" ");
				}
				System.out.printf("\n");
			}
			return;
		}
		for(int i=sum;i<30;i++) {//递归全排列1~30
			num[fm]=i;//遍历得到分母存入数组
			cmp(fm+1,num,i+1);
		}
	}
}

G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。
请问,G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。
输入格式
输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。
接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。
输出格式
输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。
样例输入1
3
1 1
样例输出1
4
样例说明
这四种方式分别是:

  1. 选1;
  2. 选2;
  3. 选3;
  4. 选2, 3。

样例输入2
7
1 1 2 2 3 3
样例输出2
40

#include<stdio.h>
#include<string.h>
int a[100001], b[100001],n, t;
int str(int i) {
    if(i > n){//假如已经将n名士兵遍历一遍,就加一
        t++;
        return t;
    }
    if(a[b[i]] == 0){//假如第i名士兵的直接上级已经出列
        str(i+1); //那么这名士兵就不能出列,直接跳到下一位
    }else{//假如第i名士兵的直接上级没有出列
        a[i] = 0; //让他出列并跳到下一位
        str(i+1);
        a[i] = i; //不让他出列并跳到下一位
        str(i+1);
    }
}
int main() {
    int i;
    while(scanf("%d", &n) != EOF){
        t = 0;
        a[0] = 1;
        for(i = 1; i <= n; i++){
            a[i] = i; //储存当前状态,如果已经出列就置为0
        }
        b[1] = 0;
        for(i = 2; i <= n; i++){
            scanf("%d", &b[i]); //记录第i号士兵的直接上级
        }
        printf("%d\n", (str(1)-1)%10007); //因为要排除没有人去的情况,所以要减一
        //G将军本人去和不去的2种情况下的方案和,去掉“G将军和它的下属全都不去”这种非法情况,再按题目要求模10007.
    }
    return 0;
}

15. 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
#include <stdio.h>
typedef int bool;//自定义bool
#define false 0
#define true 1
void cmp(int a[],int n){
    int i,j,tmp;
    bool flag;
    for(i=1;i<n;i++){
        flag=false;
        for(j=0;j<n-1;j++){
            if(a[j]>a[j+1]){
                tmp=a[j];
                a[j]=a[j+1];
                a[j+1]=tmp;
                flag=true;
            }
        }
        if(!flag){
            break;
        }
    }
}
int main()
{
    int n,i,j,k;
    scanf("%d",&n);
    int nums[n];
    for(i=0;i<n;i++){
        scanf("%d",&nums[i]);
    }
    cmp(nums,n);
    for(i=0;i<n;i++){
        printf("%d ",nums[i]);
    }
    printf("\n");
    for(i=0;i<n;i++){
        if(nums[i]==nums[i-1]){// 该处为关键点(去重):判断当前的数是否与前一个相等.
            continue;// 若相等则说明从该数开始的所有可能性已经输出,则跳过该数
        }else{
            for(j=i+1;j<n;j++){
                for(k=j+1;k<n;k++){
                    if(nums[i]+nums[j]+nums[k]==0)
                        printf("%d,%d,%d ",nums[i],nums[j],nums[k]);
                }
            }
        }
    }
    return 0;
}

AC的C

int comp(const void *a,const void *b)
{
    return *(int *)a - *(int *)b;
}

int** threeSum(int* nums, int shu02, int* shu03, int** shu04){
    *shu03 = 0;
    if (shu02 == 0) {
        return 0;
    }
    int **ret = (int **)malloc(sizeof(int *) * (shu02 + 1) * 6);
    *shu03 = 0;
    short left = 0;
    short right = shu02 - 1;;
    int target = 0;
    
    *shu04 = malloc(sizeof(int) * (shu02 + 1) * 6);
    qsort(nums, shu02, sizeof(int), comp);
    ret[*shu03] = malloc(sizeof(int) * 3);

    while (left + 1 < right) {
        int i = left + 1;
        int j = right;
        target = 0 - nums[left];
        while (i < j) {
            if (nums[i] + nums[j] < target) {
                i++;
            } else if (nums[i] + nums[j] > target) {
                j--;
            } else {
                ret[*shu03][0] = nums[left];
                ret[*shu03][1] = nums[i];
                ret[*shu03][2] = nums[j];
                (*shu04)[*shu03] = 3;
                (*shu03)++;
                ret[*shu03] = malloc(sizeof(int) * 3);

                while(nums[i] == nums[++i] && i < j) {}
                while(nums[j] == nums[--j] && i < j) {}
            }
        }
        while(nums[left] == nums[++left] && left + 1 < right) {}
    }
    return ret;
}

java

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        int len = nums.length;
        if(len < 3 || nums == null) return lists;
        //先对数组进行排序
        Arrays.sort(nums);
        for(int i = 0;i<nums.length;i++){
            //如果当前数字大于0,则不可能存在等于0的情况了
            if( nums[i] > 0) break;
            //去除重复 注::可借鉴这个写法
            if(i>0 && nums[i] == nums[i-1]) continue;
            //左指针
            int l = i+1;
            //右指针
            int r = len - 1;
            while(l < r){
                int sum = nums[i] + nums[l] + nums[r];
                if(sum == 0){
                    lists.add(Arrays.asList(nums[i],nums[l],nums[r]));
                    //前后去重
                    while(l<r && nums[l] == nums[l+1]) l++;
                    while(l<r && nums[r] == nums[r-1]) r--;
                    l++;
                    r--;
                }
                //如果数小于0 ,证明前面的数太小
                else if(sum < 0) l++;
                //如果数大于1,证明后面的数太大
                else if(sum > 0) r--;
            }
        }
        return lists;
    }
}

python

''' 特判,对于数组长度 nn,如果数组为 nullnull 或者数组长度小于 33,返回 [][]。 对数组进行排序。 遍历排序后数组: 若 nums[i]>0nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 00,直接返回结果。 对于重复元素:跳过,避免出现重复解 令左指针 L=i+1L=i+1,右指针 R=n-1R=n−1,当 L<RL<R 时,执行循环: 当 nums[i]+nums[L]+nums[R]==0nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,RL,R 移到下一位置,寻找新的解 若和大于 00,说明 nums[R]nums[R] 太大,RR 左移 若和小于 00,说明 nums[L]nums[L] 太小,LL 右移 '''
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])
                    while(L<R and nums[L]==nums[L+1]):
                        L=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res

16. 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

C

int cmp(const void *a,const void *b) {
    return *(int*)a - *(int*)b;
}
    
int threeSumClosest(int* nums, int nums2, int nums3){
    qsort(nums, nums2, sizeof(int), cmp);
    int min = INT_MAX;
    for (int i = 0;i < nums2;i++) {
        int j = i + 1;
        int k = nums2 - 1;
        int curmin = INT_MAX;
        int cha = nums3 - nums[i];
        while(j < k) {
            int sum = nums[j] + nums[k];
            if (abs(curmin) > abs(sum - cha)) {
                curmin = sum - cha;
            }
            if (sum > cha) {
                k--;
            } else if (sum < cha) {
                j++;
            } else {
                return nums3;
            }
        }
        if (abs(curmin) < abs(min)) {
            min = curmin;
        }
    }
    return nums3 + min;
}

java

class Solution {
    public int threeSumClosest(int[] arr,int t) {
        Arrays.sort(arr);//对数组进行排序
        int closeNum = arr[0] + arr[1] + arr[2];//将前三个数相加赋给closeNum,表示初始化
        for(int i = 0;i<arr.length - 2;i++) {
            int j = i+1;
            int k = arr.length - 1;
            while(j<k) {
                int tmp = arr[i]+arr[j]+arr[k];
                if(Math.abs(tmp - t) < Math.abs(closeNum - t)) {
                    closeNum = tmp;
                }
                if(tmp < t) {
                    j++;
                }else if(tmp > t) {
                    k--;
                }else {
                    return tmp;
                }
            }
        }
        return closeNum;
    }
}
//在第一层循环中for(int i = 0;i<arr.length;i++),我们定义双指针就j和k;
//j指向当前i的下一个元素,k指向末尾元素,计算三数之和并且赋给tmp,int tmp = arr[i]+arr[j]+arr[k];
//判断Math.abs(tmp - t) 和 Math.abs(closeNum - t)的大小,前者小,将前者赋给初始变量closeNum;
//之后判断tmp和目标值t的大小,大于 k--;小于j++,等于 直接返回tmp

python

''' 特判,对于数组长度nn,如果数组为Null或者数组长度小于3,返回[][]。 对数组进行排序,并定义resres,保存最接近和。 遍历排序后数组: 对于重复元素,跳过,避免重复计算(也可以不跳过) 令左指针L=i+1L=i+1,右指针R=n-1R=n−1,当L<RL<R时,执行循环: *令cur\_sum=nums[i]+nums[L]+nums[R]cur_sum=nums[i]+nums[L]+nums[R],如果cur\_sum=targetcur_sum=target,返回targettarget *若abs(cur\_sum-target)<abs(res-target)abs(cur_sum−target)<abs(res−target),说明cur\_sumcur_sum更接近目标,更新resres *若cur\_sum-targetcur_sum−target大于0,说明nums[R]nums[R]太大,RR左移 *若cur\_sum-targetcur_sum−target小于0,说明nums[L]nums[L]太小,LL右移 '''
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        n=len(nums)
        if(not nums or n<3):
            return None
        nums.sort()
        res=float("inf")
        for i in range(n):
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                sum=nums[i]+nums[L]+nums[R]
                if(sum==target):
                    return target
                if(abs(sum-target)<abs(res-target)):
                    res=sum
                if(sum-target<0):
                    L+=1
                else:
                    R-=1
        return res