一种排序--引发:java两个引用指向同一个对象
地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=8
一种排序
- 描述
-
现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复;还知道这个长方形的宽和长,编号、长、宽都是整数;现在要求按照一下方式排序(默认排序规则都是从小到大);
1.按照编号从小到大排序
2.对于编号相等的长方形,按照长方形的长排序;
3.如果编号和长都相同,按照长方形的宽排序;
4.如果编号、长、宽都相同,就只保留一个长方形用于排序,删除多余的长方形;最后排好序按照指定格式显示所有的长方形;
- 输入
-
第一行有一个整数 0<n<10000,表示接下来有n组测试数据;
每一组第一行有一个整数 0<m<1000,表示有m个长方形;
接下来的m行,每一行有三个数 ,第一个数表示长方形的编号,第二个和第三个数值大的表示长,数值小的表示宽,相等
说明这是一个正方形(数据约定长宽与编号都小于10000); - 输出
- 顺序输出每组数据的所有符合条件的长方形的 编号 长 宽
- 样例输入
-
1 8 1 1 1 1 1 1 1 1 2 1 2 1 1 2 2 2 1 1 2 1 2 2 2 1
- 样例输出
-
1 1 1 1 2 1 1 2 2 2 1 1 2 2 1
由题目:要注意一点:第二个和第三个数值大的表示长,数值小的表示宽,相等。
需要对长和宽进行处理。
思路:
其实也很简单,就是一种升序的排列,还要涉及到权重,权重(编号>长>宽),只有相等的时候,才需要比较下一个等级。并且,一个尤其重要的是:涉及到交换和移动的时候一定要整体进行。而且测试用例有点坑嗲,如果你交换或移动没有整体性的话,得出的结果和测试用例是一样的。这就导致为什么很多人士wrong answer 的。。---我就是其中一个。
第一种方法:(同样是用插入排序,把他写熟了,性能是怎么都好过冒泡排序的)
//暴力的插入排序,思想很简单,根据权重顺序进行排列,相等的时候,继续比较下一个(权重:编号,长,宽)不过不知道为何wrong answer,感觉思路是没有错的--原来是要整体性交换public void insertSortOne(Scanner sc){int n=sc.nextInt();while(n-->0){int m=sc.nextInt();int[] numArr=new int[m];int[] longArr=new int[m];int[] widthArr=new int[m];int tmpN,tmpL,tmpW,tmp;for(int i=0;i<m;i++){tmpN=sc.nextInt(); //得到编号tmpL=sc.nextInt();tmpW=sc.nextInt();if(tmpW>tmpL){ //得到长和宽tmp=tmpW;tmpW=tmpL;tmpL=tmp;}//插入排序--先实现,后面再优化--交换的时候,要当成一个整体进行交换,不是就会错,而且给出的测试案例特殊,不交换测试案例也是对的。但是肯定是wrong answerint j=i;while(j>0&&tmpN<numArr[j-1]){ //若相同跳出,插在后一个numArr[j]=numArr[j-1];longArr[j]=longArr[j-1];widthArr[j]=widthArr[j-1];j--;}numArr[j]=tmpN;if(j!=0&&numArr[j]==numArr[j-1]){ //不在数组第一位的时候,且当前和前一个相同时,就比较长//对长进行插入排序int l=j;while(l>0&&tmpL<longArr[l-1]){numArr[l]=numArr[l-1];longArr[l]=longArr[l-1];widthArr[l]=widthArr[l-1];l--;}longArr[l]=tmpL;if(l!=0&&longArr[l]==longArr[l-1]){//对宽进行排列int w=l;while(w>0&&tmpW<widthArr[w-1]){numArr[w]=numArr[w-1];longArr[w]=longArr[w-1];widthArr[w]=widthArr[w-1];w--;}widthArr[w]=tmpW;if(w!=0&&widthArr[w]==widthArr[w-1]){//说明三个都相等,把他去掉i--; //重新填充i,即可m--; //相应把for循环的长度给缩小}}else{widthArr[l]=tmpW;}}else{longArr[j]=tmpL;widthArr[j]=tmpW;}}//进行输出结果for(int i=0;i<m;i++)System.out.println(numArr[i]+" "+longArr[i]+" "+widthArr[i]);}}
第二中方法:
就是声明一个内部类,将编号,长,宽放进去。通过get,set进行修改,也是一种封装的思想(但是一个开始不是这样的,贪图方便)。尤其是插入排序,一定为涉及到数组对象的移动的。
使用前必须实例化一个对象先:rectangle[i]=new Rectangle();
直接把它写成:rectangle[j]=rectangle[j-1];对象数组存的是一个对象引用,前面这样先,相当于拷贝,即:两个引用指向了同一个对象,无论通过修改那个引用,必定会修改到同一个对象,具体查看:浅拷贝和深拷贝。留个网址(不一定是最好的):http://kuangbaoxu.iteye.com/blog/193222
所以必须做出修改,通过get,set进行赋值,移动 或者用集合,暂时没想到
rectangle[j].setNum(rectangle[j-1].getNum());
rectangle[j].setLeng(rectangle[j-1].getLeng());
rectangle[j].setWidth(rectangle[j-1].getWidth());
附上方法二:
public void insertSortTwo(Scanner sc){int n=sc.nextInt();while(n-->0){int m=sc.nextInt();Rectangle[] rectangle=new Rectangle[m];int tmpN,tmpL,tmpW,tmp;for(int i=0;i<m;i++){rectangle[i]=new Rectangle(); //先实例化出一个对象tmpN=sc.nextInt();tmpL=sc.nextInt();tmpW=sc.nextInt();if(tmpL<tmpW){ //先得出符合规则的长和宽,编号tmp=tmpL;tmpL=tmpW;tmpW=tmp;}int j=i;while(j>0&&tmpN<rectangle[j-1].num){
// rectangle[j]=rectangle[j-1]; //涉及到深拷贝和浅拷贝问题,(对象数组的引用到了同一个对象。即:内存中是两个引用指向了同一个对象,//java机制是不会分配完全两个相同的对象的不同空间的,除非有不同(hascode()不同皆可))rectangle[j].setNum(rectangle[j-1].getNum());rectangle[j].setLeng(rectangle[j-1].getLeng());rectangle[j].setWidth(rectangle[j-1].getWidth());j--;}rectangle[j].num=tmpN;if(j!=0&&rectangle[j].getNum()==rectangle[j-1].getNum()){//编号相同,进行长排序int l=j;while(l>0&&tmpL<rectangle[l-1].leng){
// rectangle[l]=rectangle[l-1];rectangle[l].setNum(rectangle[l-1].getNum());rectangle[l].setLeng(rectangle[l-1].getLeng());rectangle[l].setWidth(rectangle[l-1].getWidth());l--;}rectangle[l].leng=tmpL;if(l!=0&&rectangle[l].getLeng()==rectangle[l-1].getLeng()){//进行宽的排序int w=l;while(w>0&&tmpW<rectangle[w-1].width){
// rectangle[w]=rectangle[w-1];rectangle[w].setNum(rectangle[w-1].getNum());rectangle[w].setLeng(rectangle[w-1].getLeng());rectangle[w].setWidth(rectangle[w-1].getWidth());w--;}rectangle[w].width=tmpW;if(w!=0&&rectangle[w].getWidth()==rectangle[w-1].getWidth()){i--;m--;}}else{rectangle[l].setWidth(tmpW);}}else{ //不同的话,将相应赋值rectangle[j].setLeng(tmpL);rectangle[j].setWidth(tmpW);}}for(int i=0;i<m;i++)System.out.println(rectangle[i].getNum()+" "+rectangle[i].getLeng()+" "+rectangle[i].getWidth());}}class Rectangle{private int num,leng,width;public int getNum() {return num;}public void setNum(int num) {this.num = num;}public int getLeng() {return leng;}public void setLeng(int leng) {this.leng = leng;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}}
这题耗时挺长的,主要是纠结怎么错了,并通过这道题发现自己的不足,也是查漏补缺的机会,现在耗时长,以后就会耗时短了。
以上都是wrong answer。还以为对了。不明觉厉。
最后附上一个通过的--用的冒泡排序,难道这道题不能用插入排序???
import java.io.BufferedInputStream;
import java.util.Scanner;public class Main {public static Scanner scanner = new Scanner(new BufferedInputStream(System.in));public static void main(String[] args) {int count = scanner.nextInt();for (int i = 0; i < count; i++) {int longer = scanner.nextInt();int[] num = new int[longer];int[] length = new int[longer];int[] wide = new int[longer];for (int j = 0; j < longer; j++) {num[j] = scanner.nextInt();length[j] = scanner.nextInt();wide[j] = scanner.nextInt();if (length[j] < wide[j]) {int temp = length[j];length[j] = wide[j];wide[j] = temp;}}for (int j = 0; j < longer - 1; j++) {for (int k = j + 1; k < longer; k++) {if (num[j] < num[k]) {int temp = num[j];num[j] = num[k];num[k] = temp;temp = length[j];length[j] = length[k];length[k] = temp;temp = wide[j];wide[j] = wide[k];wide[k] = temp;} else if (num[j] == num[k] && length[j] < length[k]) {int temp = num[j];num[j] = num[k];num[k] = temp;temp = length[j];length[j] = length[k];length[k] = temp;temp = wide[j];wide[j] = wide[k];wide[k] = temp;} else if (num[j] == num[k] && length[j] == length[k]&& wide[j] < wide[k]) {int temp = num[j];num[j] = num[k];num[k] = temp;temp = length[j];length[j] = length[k];length[k] = temp;temp = wide[j];wide[j] = wide[k];wide[k] = temp;} else if (num[j] == num[k] && length[j] == length[k]&& wide[j] == wide[k]) {num[j] = Integer.MAX_VALUE;}}}for (int j = longer - 1; j >= 0; j--) {if (num[j] != Integer.MAX_VALUE) {System.out.println(num[j] + " " + length[j] + " " + wide[j]);} else {continue;}}}}
}
一种排序--引发:java两个引用指向同一个对象相关推荐
- 阶段1 语言基础+高级_1-2 -面向对象和封装_9两个引用指向同一个对象空间
新建demo03,把one的地址值赋值给two 选中的这部分因为赋值的是one地址的引用, 这里再是默认值了,不在是null值了.所以输出的内容和one是一样的. two是one玩完剩下的二手货 内存 ...
- java多态父类引用指向子类对象为什么不能调用子类特有的方法?
java多态父类引用指向子类对象为什么不能调用子类特有的方法? 我们在学习java面向对象时都会发现当父类引用指向子类对象不能调用子类特有的方法 首先我们需要了解一下java多态的具体体现 1.一个对 ...
- Java 父类的引用指向子类对象有啥用 总结
1. 你可能会写如下2个方法 feed(Cat cat){ } feed(Dog dog){ } 如果Cat.Dog都是Animal的子类,那你就可以写成 feed(Animal anim ...
- Java中父类引用指向子类对象好处
比如对于HashMap与Map的理解: HashMap 是 Map 接口的常用实现类(Map是一个接口),是一个键值对集合, 建议使用实现接口的方式使用Map,如:Map<String, Obj ...
- Java多态 父类引用指向子类对象
原文地址http://www.cnblogs.com/111testing/p/6880831.html Java多态的三个必要条件: 1. 继承 2. 子类重写父类方法 3. 父类引用指向子类对象 ...
- Java关于父类引用指向子类对象
1. 首先, java的多态是指子类重写了父类的方法,在程序运行期间(非编译),根据引用指向的"实际对象"来调用对象的方法,子类是不能重写父类的变量的. class Father{ ...
- 两个引用指向同一个数组的内存图
package com.learn.day05.demo02;public class Demo03ArraySame {public static void main(String[] args) ...
- java 父类引用指向子类对象---动态绑定
知识点: 1.java 中父类引用指向子类对象时动态绑定针对的只是子类重写的成员方法: 2.父类引用指向子类对象时,子类如果重写了父类的可重写方法(非private.非 final 方法),那么这个对 ...
- java保留两位小数4种方法,java保留两位小数4种方法,java两位小数4种
java保留两位小数4种方法,java两位小数4种 java保留两位小数4种方法 方法一:String的format方法(推荐) double f = 111231.5585; System.out. ...
最新文章
- 阿里巴巴为什么不建议直接使用 Async 注解?
- Web 开发最有用的 jQuery 插件集锦
- spring自定义作用域 依赖注入之手动注入
- Python module模块 包 __name__
- 初识exe程序反汇编小感
- HDU 4404 Worms(多边形和圆相交)
- ffmpeg 转换VC工具 V1.1.1
- 2018先进制造业产业发展白皮书
- atapi.sys 蓝屏 难度系数☆☆☆ ...
- 攻防世界misc高手进阶区funny_video完整版答案
- [转帖]*野外生活手册~
- 数字游戏-SSL 1653
- Win11更改系统文件夹的默认保存位置方法分享
- SqlServer 查询一段时间,没有数据自动补充0
- Python27 No module named PIL解决方法
- java计算机毕业设计智友少儿编程学习平台源码+mysql数据库+系统+部署+lw文档
- 《深度学习100例》目录
- 关于程序可移植性的问题
- 微信小程序自定义select下拉选择组件
- jtopo新增节点(拖拽节点到画布),<画布放大缩小或拖拽后,新增节点还在鼠标松开得位置>
热门文章
- mac 连接上l2tp但是无法访问公网
- rails 单复数转换
- 抖音、快手、西瓜制作影视解说短视频的实用工具
- C++解OJ题--最大子数组和(第一次尝试动态规划,很烧脑)
- 店梯erp,全面化运营工具助力Shopee商家高效运营店铺
- Camera sensor 基本原理
- 太及时了!13个Spring Boot练手项目,用好了,升职涨薪不用愁
- 计算机设计大赛动漫游戏,关于举办第三届大学生计算机设计大赛 暨2018年(第11届)中国大学生计算机设计大赛选拔赛的通知...
- android设备绑定微软,Android 7.1.1 手机如何登录微软账号
- 计算机启动异常卡顿,解决开机卡顿的问题,电脑卡在开机界面的解决办法