代码练习
打印金字塔
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]。
具体做法:
- 首先让差分b数组中的 b[l] + c ,a数组变成 a[l] + c ,a[l+1] + c...... a[n] + c;
- 然后我们打个补丁,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;
}