算法积累与代码练习

代码练习

打印金字塔

import java.util.Scanner;
public class Pyramid{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int total=myScanner.nextInt();//键入层数
        for(int i=1;i<=total;i++){
            //在输出*之前,还有输出 对应空格 = 总层数-当前层
            for(int j=1;j<=total-i;j++){
                System.out.print(" ");
            }
            //控制打印每层的*个数
            for(int k=1;k<=2*i-1;k++){
                //当前行的第一个位置是*,最后一个位置也是*, 最后一层全部 *
                if(k==1||k==2*i-1||i==total){
                    System.out.print("*");
                }
                else{   //其他情况输出空格
                    System.out.print(" ");
                }
            }
            //每打印完一层的*后,就换行 println 本身会换行
            System.out.println(" ");
        }

    }
}

路口交费(while循环)

某人有100,000元,每经过一次路口,需要交费,规则如下:

1.当现金>50000时,每次需要交5%

2.当现金<=50000时,每次交1000

计算该人需要交费多少次*/

public class Lukoujiaofei{
    public static void main(String[] args){
        int p = 0;
        int money = 100000;
        while(true){
            if(money>50000){ //当现金大于50000时
                money*=0.95;
                p++;
            }
            else if(money>1000){ //当现金<=50000时
                money-=1000;
                p++;
            }
            else{ //当现金不足1000时,退出循环,记录截止
                break;
            }
        }
        System.out.print("该人一共经过"+p+"次路口");
    }
}

判断水仙花数

//判断一个数是否为水仙花数,即个十百位数

import java.util.Scanner;
public class Daffodil{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int number = myScanner.nextInt();
        int a,b,c;//用于接收个十百位数
        a=number/100; //百位数
        b=number/10%10;//十位数
        c=number%10;//个位数
        if((a*a*a+b*b*b+c*c*c)==number){
            System.out.println("这是个水仙花数");
        }
        else{
            System.out.println("这不是水仙花数");
        }

    }
}

1.移除元素

class Solution {
    public int removeElement(int[] nums, int val) {
        
        int j=0;
        for(int i=0;i<nums.length;i++){
            
            if(nums[i]!=val){
                nums[j++]=nums[i];
            }
        }
        return j;
    }
}

2.快乐交换

#include <iostream>
#include <string.h>
using namespace std;
int main(){
    string a,b;
    cin>>a>>b;
    cout<<b<<a;
    return 0;
}

3.最大公约数

#include <iostream>
using namespace std;
typedef long long  int ll ;
ll gcd(ll x,ll y);
int main(){
    ll a,b;
    cin>>a>>b;
    cout<<gcd(a,b);
    return 0;
}
ll gcd(ll x,ll y){  
    ll z = y;
    while(x%y!=0)
    {
        z = x%y;
        x = y;
        y = z;  
    }
    return z;
}
​
​

4.判断字符或字符数

#include <iostream>
#include <string.h>
using namespace std;
int main(){
    char a;
    cin>>a;
    if((a>='a'&&a<='z')||(a>='A'&&a<='Z')){
        cout<<"character";
    }
    else if(a>=0&&a<=9){
        cout<<"digit";
    }
    else{
        cout<<"ERROR";
    }
​
​
    return 0;
​
}

5.最长公共前缀

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        }
        int length = strs[0].length();
        int count = strs.length;
        for (int i = 0; i < length; i++) {
            char c = strs[0].charAt(i);
            for (int j = 1; j < count; j++) {
                if (i == strs[j].length() || strs[j].charAt(i) != c) {
                    return strs[0].substring(0, i);
                }
            }
        }
        return strs[0];
    }
}
​

算法积累

1)二分查找

问题描述:

请实现无重复数字的升序数组的二分查找:给定一个 元素升序的、无重复数字的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标(下标从 0 开始),否则返回 -1。

问题分析:

既然数组是有序的,从一边开始逐一寻找并不高效,不如从数组头尾同时寻找,确定一个中间值,该值大于目标数,则往数组左边找,反之往右边找。

具体做法:
  • step 1:从数组首尾开始,每次取中点值。
  • step 2:如果中间值等于目标即找到了,可返回下标,如果中点值大于目标,说明中点以后的都大于目标,因此目标在中点左半区间,如果中点值小于目标,则相反。
  • step 3:根据比较进入对应的区间,直到区间左右端相遇,意味着没有找到。
代码实现(java):
import java.util.*;
public class Solution {
    public int search (int[] nums, int target) {
        int l = 0;
        int r = nums.length - 1;
        //从数组首尾开始,直到二者相遇
        while(l <= r){ 
            //每次检查中点的值
            int m = (l + r) / 2; 
            if(nums[m] == target)
                return m;
            //进入左的区间
            if(nums[m] > target) 
                r = m - 1;
            //进入右区间
            else 
                l = m + 1;
        }
        //未找到
        return -1; 
    }
}

2)差分思想

原理:

假设有原数组a[i]和数组b[i];

a[i]=b[1]+b[2]+...+b[i]-->b[i]=a[i]-a[i-1];

即数组a[i]是数组b的前缀项和,反之数组b[i]是a的差分项。

问题描述:

输入一个长度为 n 的整数序列。

接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。

请你输出进行完所有操作后的序列

问题分析:

给定区间 [l , r] ,把a数组在此区间的所有数加上c。若直接把该区间a每一个数循环加不太高效。我们考虑利用b数组和a的关系:b[n]=a[n]-a[n-1]。

具体做法:

  1. 首先让差分b数组中的 b[l] + c ,a数组变成 a[l] + c ,a[l+1] + c...... a[n] + c;
  2. 然后我们打个补丁,b[r+1] - c, a数组变成 a[r+1] - c,a[r+2] - c......a[n] - c;
代码实现:
//差分 时间复杂度 o(m)
#include<stdio.h>
const int N = 1e5 + 10;
int main()
{
    int a[N], b[N];
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        b[i] = a[i] - a[i - 1];      //构建差分数组
    }
    int l, r, c;
    while (m--)
    {
        scanf("%d%d%d", &l, &r, &c);
        b[l] += c;     //将序列中[l, r]之间的每个数都加上c
        b[r + 1] -= c;
    }
    for (int i = 1; i <= n; i++)
    {
        a[i] = b[i] + a[i - 1];    //前缀和运算
        printf("%d ", a[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值