仅作为个人学习笔记,大佬勿喷!
1.超级水王
/**
* 超级水王,数组中某个数出现的次数超过nums.length/2 ,则称该数组有超级水王数,返回该数
* 要求数组最多只能遍历两次,空间复杂度为O(1)
* @param nums
* @return
*/
public static void supperWaterKing(int[] nums){
if(nums==null || nums.length==0){
System.out.println("没有水王数");
return;
}
int target=0;
int hp=0;
for (int num : nums) {
if(hp==0){
target=num;
hp++;
}else if(num==target){
hp++;
}else{
hp--;
}
}
if(hp==0){
System.out.println("没有超级水王");
return;
}
int count=0;
for (int num : nums) {
if(num==target){
count++;
}
}
if(count>nums.length/2)
System.out.println("超级水王数是"+target);
}
解题思路:
数值中每次啊删除两个不同的数,如果最后没有剩余数,则一定没有水王数。最后数组中有剩余数不一定有超级水王数,拿剩下的数再次遍历数组,获取出现次数来判断最终结果。
核心在于如何快速的删除两个不同的数。
2.转圈打印
public static void circlePrint(int[][] nums){
if(nums==null|| nums.length==0 || nums[0].length==0){
return;
}
int leftUpRow=0;
int leftUpList=0;
int rightDownRow=nums.length-1;
int rightDownList=nums[0].length-1;
while (leftUpList<=rightDownList && leftUpRow<=rightDownRow){
if(leftUpList==rightDownList && leftUpRow==rightDownRow){
System.out.print(nums[leftUpRow][leftUpList]);
}else {
if(leftUpRow==rightDownRow){
for (int list = leftUpList; list <=rightDownList ; list++) {
System.out.print(nums[leftUpRow][list]+" " );
}
}else if(leftUpList==rightDownList){
for (int row = leftUpRow; row <=rightDownRow ; row++) {
System.out.print(nums[row][leftUpList] +" " );
}
}else {
for(int list=leftUpList;list<rightDownList;list++){
System.out.print(nums[leftUpRow][list] +" " );
}
for (int row = leftUpRow; row <rightDownRow ; row++) {
System.out.print(nums[row][rightDownList]+" " );
}
for(int list=rightDownList;list>leftUpList;list--){
System.out.print(nums[rightDownRow][list]+" " );
}
for(int row=rightDownRow;row>leftUpRow;row--){
System.out.print(nums[row][leftUpList] +" " );
}
}
}
leftUpRow++;
leftUpList++;
rightDownList--;
rightDownRow--;
}
}
解题思路:
找到左上角、右下角的旋转打印。判断左上角和右下角同一个位置时、同一行不同列时、同一列不同行时,不同行不同列四种情况打印即可
3.Z字形打印
/**
* @Author WXK
* @Description 之字形打印
* @Date 10:00 2022/1/18
**/
public static void zigzagPrint(int[][] nums){
if(nums==null || nums.length ==0 ||nums[0].length==0){
return;
}
int rightRow=0;
int rightColumn=0;
int downRow=0;
int downColumn=0;
int endRow=nums.length-1;
int endColumn=nums[0].length-1;
boolean flag=false;
while (rightRow !=endRow+1){
print(nums,rightRow,rightColumn,downRow,downColumn,flag);
rightRow=rightColumn==endColumn?rightRow+1:rightRow;
rightColumn=rightColumn==endColumn?rightColumn:rightColumn+1;
downColumn=downRow==endRow?downColumn+1:downColumn;
downRow=downRow==endRow?downRow:downRow+1;
flag=!flag;
}
}
/**
* @Author WXK
* @Description 打印
* @Date 14:44 2022/1/18
**/
public static void print(int[][] nums,int rightRow,int rightColumn,int downRow,int downColumn,boolean flag){
if(flag){
while (rightRow!=downRow+1){
System.out.print(nums[rightRow++][rightColumn--]+" ");
}
}else {
while (downRow!=rightRow-1){
System.out.print(nums[downRow--][downColumn++]+" ");
}
}
}
解题思路:
一定要从宏观角度观察其规律。使用两个指针,一个指针先向右移动,移动到最后一列之后,改为向下移动;另一个指针先向下移动,移动到最后一行时,改为向右移动。移动中的两个指针必定在同一斜线上。通过flag来控制方向。
4、找出数组中唯一一个出现奇数次的数 数组中只有一种数,出现奇数次,其他所有数都出现了偶数次 怎么找到这唯一出现了奇数次的数字
public static void getUnevennumber(int[] nums){
if(nums!=null && nums.length>0){
int number=0;
for (int num : nums) {
num^=number;
}
System.out.println(number);
}
}
解题思路:
0异或任何数都为该数本身,异或满足交换律,交换计算后不影响最终结果。一个数异或本身都为零
故最后剩下的一定是奇数次的数
5.寻找明星
给定一个数n,所有人的编号从0到n-1
给定一个函数 boolean know(int i, int j),
该函数表示i这个人认不认识j这个人,认识关系是单向的
有了这个函数,你可以检查认识这件事情。
规定何为明星?
1)所有人都认识这个人
2)这个人不认识自己之外的所有人
那么这个人就是明星
利用know函数,找到明星,返回明星的编号,如果没有明星返回-1。
Leetcode题目 :
https://leetcode.com/problems/find-the-celebrity/
/**
* 系统默认给定函数
* @param x
* @param i
* @return
*/
public static boolean knows(int x, int i) {
return true;
}
/**
* 寻找明星
* @param n
* @return
*/
public static int findCelebrity(int n){
int can=0;
for (int i = 0; i < n; i++) {
if(knows(can,i)){
can=i;
}
}
//最后拿到can对应的数,在遍历一次,判盯can是否为明星
//can右侧都是他不认识的,只需判断左侧 明星除了自己不认识其他人
for(int i=0;i<can;i++){
if(knows(can,i)){
return -1;
}
}
//所有人都认识明星
for(int i=0;i<n;i++){
if(!knows(i,can)){
return -1;
}
}
return can;
}