目录
排序子序列_牛客笔试题_牛客网
牛牛定义排序子序列为一个数组中一段连续的子序列,并且这段子序列是非递增或者非递减排序的。牛牛有一个长度为n的整数数组A,他现在有一个任务是把数组A分为若干段排序子序列,牛牛想知道他最少可以把这个数组分为几段排序子序列.
简单来说:给你一个数组,然后进行分段,分段的方法:每一段要么非递减要么非递增并且要求分段序列最少。
比如:1 2 3 2 2 1,(1 2 3)这段非递减,那就分成一段,(2 2 1)这段非递增那就分成另一段。
思路:那就需要两个哨兵定位,一个定位起始位置,一个向后循环,只要满足非递增或非递减就一直循环(前提是不能数组越界),若不满足,则停止,此时段数加1,并且起始位置的哨兵移动到后面哨兵的位置,后面哨兵继续移动。
实现一:由于是前一个与后一个进行判断,在最后一个判断时,会出现数组越界问题,因此要将判断条件改写为 i < arr.length - 1;最后单独判断最后一个。(就是最后一个也是一个序列的情况)
import java.util.Scanner;
public class TestDemo {
//题意:找非递增或者非递减序列并且序列连续
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
int[] arr = new int[num];
for(int i = 0; i < arr.length; ++i){
arr[i] = scanner.nextInt();
}
int lenNum = countMin(arr);
System.out.println(lenNum);
}
//写个函数吧,判断
public static int countMin(int[] arr){
int count = 0;
for(int i = 0; i < arr.length; i++){
/**
* 得先判断越界问题,
*/
if(i < arr.length - 1 && arr[i] == arr[i+1]){
continue;
}
if(i < arr.length - 1 && arr[i] <= arr[i+1]){
while(i < arr.length - 1 && arr[i] <= arr[i+1]){
i++;
}
count++;
continue;
}
if(i < arr.length - 1 && arr[i] >= arr[i+1]){
while(i < arr.length - 1 && arr[i] >= arr[i+1]){
i++;
}
count++;
continue;
}
count++;//可能最后一个是单独一个
//此时要注意for循环这块还有个i++
}
return count;
}
}
实现二:如果不愿意单独判断一次,那就将数组的大小额外扩充一位,这样就不会越界。
import java.util.Scanner;
public class Main {
//题意:找非递增或者非递减序列并且序列连续
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] arr = new int[n + 1];
for(int i = 0; i < arr.length - 1; ++i){
arr[i] = scanner.nextInt();
}
int count = 0;
int i = 0;
while(i < n){ //for(int i = 0; i < n; i++) 这样下面可省略
//判断开头就是 1 1 1 这种情况
if(arr[i] == arr[i+1]){
i++;
}else if(arr[i] > arr[i+1]){
while(i < n && arr[i] >= arr[i+1]){
i++;
}
count++;
i++; //若用for可省略
}else{
while(i < n && arr[i] <= arr[i+1]){
i++;
}
count++;
i++; //若用for可省略
}
}
System.out.println(count);
}
}
倒置字符串_牛客题霸_牛客网
将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I
思路一:使用String类的split()方法,存储每一个单词,并逆序输出split()方法的讲解:6.字符串拆分
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
String[] arr = str.split(" ");
for(int i = arr.length - 1; i >= 0; --i){
System.out.print(arr[i]+" ");
}
}
}
思路二:将整体字符串逆置,接着将每个单词再次逆置,这样能能得到结果
遇到的问题:在一个单词循环完后,此时要么是遇到空格,要么越界,因此要进行判断,
不能用此条件判断!!!:if(str.charAt(j) == ' '){,因为最后一次下标必然越界,用此方法会直接抛出字符串越界异常的!!!
import java.util.Scanner;
public class Main{
//字符串转置
public static void reverse(char[] arr,int left,int right){
while(left < right){
char temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();//next遇到空格会截止
char[] arr = str.toCharArray();
//先整体转置
reverse(arr,0,arr.length - 1);
//接着每个单词进行转置
//两种情况转置 1.遇到空格将前面那一段转置 2.数组越界 将最后一个转置
int i = 0;
while(i < arr.length){
int j = i;
while(j < arr.length && arr[j]!= ' '){
j++;
}
//此时要么遇到空格了,要么就是j越界,那就判断一下
//如果遇到空格
/**
* if(str.charAt(j) == ' '){错误写法,此写法在判断最后一次时
* 会使用越界下标,因此会出现数组越界问题
*/
if(j < arr.length){
reverse(arr,i,j - 1);
i = j + 1;//j此时为空格,需要跳向下一个
}else{
//越界
reverse(arr,i,j - 1);
break;
}
}
String ret = new String(arr);
System.out.println(ret);
}
}