http://blog.csdn.net/pipisorry/article/details/44411541
Random()函数生成随机数
java.util.Random例子:
随机数种子的作用:
例子来做说明:
java.lang.Math.Random
两个随机函数到底的特点:
ref:http://blog.sina.com.cn/s/blog_93dc666c0101h3gd.html
http://blog.csdn.net/pipisorry/article/details/44411541
java.lang.Math.Random
两个随机函数到底的特点:
ref:http://blog.sina.com.cn/s/blog_93dc666c0101h3gd.html
如何快速求取一段区间的平均值 用前缀的思想来看 非常简单
但是 本题题意要求的是 大于等于一段长度的区间的平均值的最大值 而且给出的数据范围很大 O(n*L)的直白比较算法 用于解决此问题不合适
这种情况下 可以考虑用斜率来表示平均值 然后通过对斜率的讨论和比较斜率来找出最大平均值
我感觉是维护一个从当前点往前的最大斜率——去除上凸点(它和当前点的连线肯定不能是最大斜率)
code(别人的orz...)
#include <stack> #include <cstdio> #include <list> #include <cassert> #include <set> #include <iostream> #include <string> #include <vector> #include <queue> #include <functional> #include <cstring> #include <algorithm> #include <cctype> #include <string> #include <map> #include <cmath> using namespace std; #define LL long long #define ULL unsigned long long #define SZ(x) (int)x.size() #define Lowbit(x) ((x) & (-x)) #define MP(a, b) make_pair(a, b) #define MS(arr, num) memset(arr, num, sizeof(arr)) #define PB push_back #define X first #define Y second #define ROP freopen("input.txt", "r", stdin); #define MID(a, b) (a + ((b - a) >> 1)) #define LC rt << 1, l, mid #define RC rt << 1|1, mid + 1, r #define LRT rt << 1 #define RRT rt << 1|1 const double PI = acos(-1.0); const int INF = 0x3f3f3f3f; const double eps = 1e-8; const int MAXN = 1e5 + 10; const int MOD = 1e9 + 7; const int dir[][2] = { {-1, 0}, {0, -1}, { 1, 0 }, { 0, 1 } }; int cases = 0; typedef pair<int, int> pii; int Q[MAXN], arr[MAXN]; char str[MAXN]; int Check(int x1, int x2, int x3, int x4) { return (arr[x2] - arr[x1-1]) * (x4-x3+1) - (arr[x4]-arr[x3-1])*(x2-x1+1); } int main() { //ROP; int T; scanf("%d", &T); while (T--) { int len, L; scanf("%d%d", &len, &L); scanf("%s", str+1); for (int i = 1; i <= len; i++) arr[i] = arr[i-1] + str[i] - '0'; int head = 0, tail = 0; pii ans = MP(1, L); for (int i = L; i <= len; i++) { int j = i-L; while (head+1 < tail && Check(Q[tail-2], j, Q[tail-1], j) >= 0) tail--; Q[tail++] = j+1; while (head+1 < tail && Check(Q[head], i, Q[head+1], i) <= 0) head++; int tmp = Check(Q[head], i, ans.X, ans.Y); if (tmp > 0 || (tmp == 0 && i - Q[head] < ans.Y - ans.X)) ans.X = Q[head], ans.Y = i; } printf("%d %d\n", ans.X, ans.Y); } return 0; }
一、过滤器的作用
过滤器用来格式化需要展示给用户的数据。
在HTML中的模板绑定符号{{ }}内通过|符号来调用过滤器。例如,假设我们希望将字符串转换成大写可以对字符串中的每个字符都单独进行转换操作,也可以使用过滤器:{{name | uppercase }}
◇给过滤器传参数:
<h3>货币格式</h3>
{{123|currency}}
<H3>小数位数</H3>
{{123.3213132|number:2}}
<H3>大写转换</H3>
{{'tanzhenngqiang'|uppercase}}
<H3>小写转换</H3>
{{'TANZHENGQIANG'|lowercase}}
◆number过滤器将数字格式化成文本。它的第二个参数是可选的,用来控制小数点后截取的位数。
如果传入了一个非数字字符,会返会空字符串
◆可以用|符号作为分割符来同时使用多个过滤器。
二、filter过滤器
可以从给定数组中选择一个子集,并将其生成一个新数组返回。这个过滤器通常用来过滤需要进行展示的元素。例如,在做客户端搜索时,可以从一个数组中立刻过滤出所需的结果。
这个过滤器的第一个参数可以是字符串、对象或是一个用来从数组中选择元素的函数。
示例:
①过滤包含字母e的单词
{{['Ari','Lerner','Likes','To','Eat','Pizza'] | filter:'e' }}
②过滤对象
{{ [
{ 'name': 'Ari',
'City': 'San Francisco',
'favorite food': 'Pizza' },
{ 'name': 'Nate',
'City': 'San Francisco',
'favorite food': 'indianfood'
}] | filter:{'favorite food': 'Pizza'} }}
③自定义函数进行过滤
◇isCapitalized函数的功能是根据首字母是否为大写返回true或false。
$scope.isCapitalized= function(str) {
return str[0] == str[0].toUpperCase();
};
使用自定义过滤函数
{{['Ari','likes','to','travel'] | filter:isCapitalized }}
<!--["Ari"] -->
我们也可以给filter过滤器传入第二个参数,用来指定预期值同实际值进行比较的方式。
第二个参数可以是以下三种情况之一。
◇true
用angular.equals(expected, actual)对两个值进行严格比较。
◇ false
进行区分大小写的子字符串比较。
◇函数
运行这个函数,如果返回真值就接受这个元素。
★JSON过滤器
json过滤器可以将一个JSON或JavaScript对象转换成字符串。这种转换对调试非常有帮助,例如:
{{ {'name':'Ari', 'City': 'SanFrancisco'} | json }}
<!--
{
"name": "Ari",
"City": "San Francisco"
}
-->
★limitTo过滤器(截取字符串)
limitTo过滤器会根据传入的参数生成一个新的数组或字符串,新的数组或字符串的长度取决于传入的参数,通过传入参数的正负值来控制从前面还是从后面开始截取。
如果传入的长度值大于被操作数组或字符串的长度,那么整个数组或字符串都会被返回。
例如,我们可以截取字符串的前三个字符:
{{ San Francisco is very cloudy | limitTo:3 }}
<!-- San -->
或最后的六个字符:
{{ San Francisco is very cloudy | limitTo:-6 }}
<!-- cloudy -->
对数组也可以进行同样的操作。返回数组的第一个元素:
{{ ['a','b','c','d','e','f'] | limitTo:1 }}
<!--["a"] -->
★orderBy过滤器
orderBy过滤器可以用表达式对指定的数组进行排序。orderBy可以接受两个参数,第一个是必需的,第二个是可选的。第一个参数是用来确定数组排序方向的谓词。
下面分情况讨论第一个参数的类型。
l 函数
当第一个参数是函数时,该函数会被当作待排序对象的getter方法。
l 字符串
对这个字符串进行解析的结果将决定数组元素的排序方向。可以传入+或-来强制进行升序或降序排列。
l 数组
在排序表达式中使用数组元素作为谓词。对与表达式结果并不严格相等的每个元素,则使用第一个谓词。
第二个参数用来控制排序的方向(是否逆向)。
'name': 'Ari',
'status': 'awake'
},{
'name': 'Q',
'status': 'sleeping'
},{
'name': 'Nate',
'status': 'awake'
}] | orderBy:'name' }}
结果:
[
{"name":"Ari","status":"awake"},
{"name":"Nate","status":"awake"},
{"name":"Q","status":"sleeping"}
]
也可以对排序结果进行反转。例如,通过将第二个参数设置为true可以将排序结果进行反转:
{{ [{
'name': 'Ari',
'status': 'awake'
},{
'name': 'Q',
'status': 'sleeping'
},{
'name': 'Nate',
'status': 'awake'
}] | orderBy:'name':true }}
三、自定义过滤器
创建自定义过滤器需要将它放到自己的模块中。
◇实现一个过滤器,将字符串第一个字母转换为大写。
过滤器本质上是一个会把我们输入的内容当作参数传入进去的函数。上面这个例子中,我们在调用过滤器时简单地把input当作字符串来处理。可以在这个函数中做一些错误检查:
angular.module('myApp.filters', []).filter('capitalize', function() {
returnfunction(input) {
// input是我们传入的字符串
if (input) {
return input[0].toUpperCase() + input.slice(1);
}
};
});
现在,如果想将一个句子的首字母转换成大写形式,可以用过滤器先将整个句子都转换成小
写,再把首字母转换成大写:
<!-- Ginger loves dog treats -->
{{ 'ginger loves dog treats' | lowercase | capitalize}}
钩子的本质是一段用以处理系统消息程序,通过系统调用把它挂入系统。钩子种类很 多,每种钩 子可以截获并处理相应的消息当特定发出在到达目窗口之前,每种钩子可以截获并处理相应的消息,每当特定消息发出,在到达目窗口之前,钩子程序先行截获该消息、得到对此消息的控制权。此时钩函数可以对截获的消息进加工处理,甚至可以强制结束消息的传递。这有点类似与 MFC中的 PreTranslateMessage函数数,所不同的是该函数只能用于拦截本进程中消息,而对系统则无为力。
钩子分为全局的钩子和局部的钩子。局部的钩子在程序中写钩子的过程函数就可以了。全局的钩子,则需要在dll中写出过程函数,然后在程序中进行连接使用。
1.用SetWindowsHookEx安装钩子
HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \\钩子类型,例如WH_MOUS、 WH_KEYBOARDWH_KEYBOARD
__in HOOKPROC lpfn, \\回调函数地址,当钩子钩到任何消息后便调用这个函数;
__in HINSTANCE hMod, \\实例句柄,钩子所在模块的句柄
__in DWORD dwThreadId); \\线程ID,指定想让钩子去哪个线程,为 0则拦截整个系统消息此为全局钩子。如果指定确定的线程,即为专用钩子
2.定义钩子函数
LRESULT WINAPI MyHookProc(
int nCode , // 指定是否需要处理该消息
WPARAM wParam, // 包含该消息的附加消息
LPARAM lParam // 包含该消息的附加消息
)
钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。参数wParam和lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。
得到控制权的钩子函数在处理完消息后,可以调用另外一个API函数 CallNextHookEx来继续传递该消息,也可以通过直接返回 TRUE来丢弃该消息,阻止该消息继续传递。
3.调用CallNextHookEx把钩子信息传递给钩子链的下一个钩子函数。原型如下:
LRESULT CallNextHookEx(
HHOOK hhk, //传递给的钩子句柄
int nCode, //下一个钩子程序使用此代码,以确定如何处理钩的信息
WPARAM wParam, //要传递的参数
LPARAM lParam //要传递的参数
)
当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。
4.用UnhookWindowsHookEx卸载钩子
UnhookWindowsHookEx
(
HHOOK hhk; //要卸载的钩子
);
函数成功返回TRUE,否则返回FALSE。
例子:
实现一个线程级的鼠标钩子。钩子跟踪当前窗口鼠标移动的位置变化信息。并输出到窗口。
(1)在VC中利用MFC APPWizard生成一个不使用文档/视结构的单文档应用mousehook。打开childview.cpp文件,加入全局变量:
HHOOK hHook;//鼠标钩子句柄
CPoint point;//鼠标位置信息
CChildView*pView;//鼠标钩子函数用到的输出窗口指针
在CChildView::OnPaint()添加如下代码:
CPaintDCdc(this);
charstr[256];
sprintf(str,“x=%d,y=%d",point.x,point.y);//构造字符串
dc.TextOut(0,0,str);//显示字符串
(2)childview.cpp文件中定义全局的鼠标钩子函数。
LRESULT CALLBACK MouseProc( intnCode,WPARAMwParam,LPARAMlParam)
{
//是鼠标移动消息
if(wParam==WM_MOUSEMOVE||wParam==WM_NCMOUSEMOVE)
{
point=((MOUSEHOOKSTRUCT*)lParam)->pt;//取鼠标信息
pView->Invalidate();//窗口重画
}
//传递钩子信息
return CallNextHookEx(hHook,nCode,wParam,lParam);
}
(3)CChildView类的构造函数中安装钩子。
CChildView::CChildView(){
pView=this;//获得输出窗口指针
hHook=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());
}
(4)CChildView类的析构函数中卸载钩子。
CChildView::~CChildView()
{
if(hHook)
UnhookWindowsHookEx(hHook);
}
problem:
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.
thinking:
(1)
对照举例
个位数举例
Ⅰ,1 】Ⅱ,2】 Ⅲ,3】 Ⅳ,4 】Ⅴ,5 】Ⅵ,6】Ⅶ,7】 Ⅷ,8 】Ⅸ,9 】
十位数举例
Ⅹ,10】 Ⅺ,11 】Ⅻ,12】 XIII,13】 XIV,14】 XV,15 】XVI,16 】XVII,17 】XVIII,18】 XIX,19】 XX,20】 XXI,21 】XXII,22 】XXIX,29】 XXX,30】 XXXIV,34】 XXXV,35 】XXXIX,39】 XL,40】 L,50 】LI,51】 LV,55】 LX,60】 LXV,65】 LXXX,80】 XC,90 】XCIII,93】 XCV,95 】XCVIII,98】 XCIX,99 】
百位数举例
C,100】 CC,200 】CCC,300 】CD,400】 D,500 】DC,600 】DCC,700】 DCCC,800 】CM,900】 CMXCIX,999】
千位数举例
M,1000】 MC,1100 】MCD,1400 】MD,1500 】MDC,1600 】MDCLXVI,1666】 MDCCCLXXXVIII,1888 】MDCCCXCIX,1899 】MCM,1900 】MCMLXXVI,1976】 MCMLXXXIV,1984】 MCMXC,1990 】MM,2000 】MMMCMXCIX,3999】
(2)避免N多条件判断的技巧:利用罗马数字自身的规律,减去一个基数,来简化复杂度
code:
class Solution { public: string intToRoman(int num) { int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; string numerals[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }; string result; for (int i = 0; i < 13; i++) { while (num >= values[i]) { num -= values[i]; result.append(numerals[i]); } } return result; } };
#include<boost/filesystem.hpp> { boost::filesystem::path path("/test/test1"); //初始化 boost::filesystem::path old_cpath=boost::filesystem::current_path(); //取得当前目录 boost::filesystem::path file_path = old_cpath / "file"; //path支持重载/运算符 if(boost::filesystem::exists(file_path)) //判断文件存在性 { std::string strPath = file_path.string(); int x = 1; } else { //目录不存在; boost::filesystem::create_directory(file_path); //目录不存在,创建 } bool bIsDirectory = boost::filesystem::is_directory(file_path); //判断file_path是否为目录 boost::filesystem::recursive_directory_iterator beg_iter(file_path); boost::filesystem::recursive_directory_iterator end_iter; for (; beg_iter != end_iter; ++beg_iter) { if (boost::filesystem::is_directory(*beg_iter)) { continue; } else { std::string strPath = beg_iter->path().string(); //遍历出来的文件名 int x=1; } } boost::filesystem::path new_file_path = file_path / "test.txt"; if(boost::filesystem::is_regular_file(new_file_path)) //判断是否为普通文件 { UINT sizefile = boost::filesystem::file_size(new_file_path); //文件大小(字节) int x =1; } boost::filesystem::remove(new_file_path);//删除文件new_file_path }
3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
yes no yes
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int d[30] , m , sum = 0; bool visited[30] ; bool DFS(int len , int c ,int pos) { if(c==4) { return true ; } if(sum == len) { if(DFS(0,c+1,0)) { return true ; } } else { for(int i = pos ; i < m ; ++i) { if(!visited[i]) { if(len+d[i]>sum) { return false; } visited[i] = true ; if(DFS(len+d[i],c,i+1)) { return true ; } visited[i] = false ; } } } return false ; } int main() { int n ; scanf("%d",&n); while(n--) { scanf("%d",&m); sum = 0 ; for(int i = 0 ; i < m ; ++i) { scanf("%d",&d[i]) ; sum += d[i] ; } if(m<4 || sum%4!=0) { puts("no") ; } else { sort(d,d+m) ; sum /= 4 ; if(sum<d[m-1]) { puts("no") ; continue ; } memset(visited,false,sizeof(visited)) ; if( DFS(0,0,0) ) { puts("yes") ; } else { puts("no") ; } } } return 0 ; }
快速排序是一种分治排序算法。它将数组划分为左右两个部分,然后分别对这两部分排序。关键在划分的过程中,它将重排数组,使的以下条件成立:
我们通过划分完成排序,然后递归的调用该方法处理子文件,每一次划分都会至少使一个元素放到它最终的位置上。
void quick_sort(Item a[], int l, int r)
{
if(r <= l)
return;
Item v = a[r];
int i = partation(a, l, r);
quick_sort(a, l, i-1);
quick_sort(a, i+1, r);
}
int partation(Item a[], int l, int r) //划分函数
{
int i = l-1, j = r;
Item v = a[r];
for(;;)
{
while(less(a[++i], v));
while(less(v, a[--j]))
if(j == l) //v是数组中的最小值
break;
if(j <= i) //i, j相遇
break;
exch(&a[i], &a[j]);
}
exch(&a[i], &a[r]); //交换划分元素到它最终位置
return i;
}
划分过程是不稳定的,因为每个元素都有可能被移到大量和它相等的元素(未经检测到)的后面。至今,没有基于数组的快速排序时稳定的。
时间复杂度
如果调用一个大小为N的有序文件,那么所有的划分都将退化,程序会调用自身N次,每次调用减少一个元素(左侧N-1个,右侧1个……);
时间复杂度
如果每次划分都能够恰好把文件分割成大小相等的两部分,即满足分治法
递归树的深度是
时间复杂度
直观来看就是,最好情况和最坏情况每层交替出现
在一个差的划分后接一个好的划分,以下配图《算法导论》P99
1.《算法:C语言实现》P192
2.《算法导论》P98
3. 主定理:https://www.zybuluo.com/quinn/note/77106
职场上的新人,经常会说一句话:这个对我没用。比如现在做java开发,python对我没用,现在做开发,项目管理对我没用,大学课程没用,数学物理化学没用。这种功利的想法其实有个问题,就是这个世界上根本不存在多少有用的知识。没有什么三句话就能说清楚的秘诀可以让你的工作变轻松或者让你拿到更多的收入。
有句古老的谚语说机会总是留给有准备的人,没有谁有能力恰好掌握刚刚够用的知识,也没谁能把握住命运的脉络预言自己绝不会走上某条道路。——我绝不在考勤机里录入指纹,因为我要给自己留下犯罪的机会。从另外一侧看,也没有任何人会因为你会java就给你一个架构师的岗位或者项目主管的岗位,只因为你狭窄的知识面就认为你的学习能力超强,在短期内就能胜任新的岗位。这个道理其实很好懂,只是有些人的脑子不具备将这个道理映射到现实中的能力,以至于发现这些人在整天抱怨之余,其实根本没有任何努力,如果这些人成功了,那才叫逆天了。
曾经我面试过一个人,他的理想是成为架构师,我问他为这个目标做了什么,他说还没有做什么(其实他做了,比如熟读语言、培养情怀、寻找符合架构师身份的桌面等等,只是被我认为没做什么),我又问他那现在离架构师还有多少差距,他说就差一个机会了(有种只差两个人了的即视感……),于是就给了他这么个机会让他当场设计一个很小的功能,然后,就没有然后了。所以说面试宝典信的都是傻子,面试官普遍都是只要你舍得死我就舍得埋的主,不要想着靠技巧赢得差距太大的胜利。人生就像是冰山,那些很稳的人,水面以下的部分超过90%,你以为自己只需要水面以上的部分就太幼稚了。
实际上超过99.99%的知识你压根无法预测会用在什么地方,就连识字都是你认识1500个字就差不多可以保证平庸的生活了,但是想靠1500个字打天下还是有些困难,小学生都被要求认识2500个字,指不定哪天给自己的娃起名字的时候就用到了,如果你只能想起来什么二蛋、狗剩之类的名字,很可能你的女朋友不会愿意嫁给你。嗯嗯,刚才您的打开方式不正确,请重新打开……咳咳,这回好了。好了,其实让你在人类社会中生活的更好的主要是人文情怀,或者说是让你看起来跟隔壁班那个傻子差距更大的东西,虽然你永远没有机会走出奥尔特云,但是如果你可以给一个同样走不出去的地球人讲三体的故事,还是更容易获得大家的认同,也更容易在竞争中获得胜利——因为在正规战中,大家那些胜任岗位所需的知识都很贫瘠,只能靠拼才艺才能区分胜负了。
扯了这么多,其实总结起来就一点,决定你人生幸福的都是你觉得没用的那些知识。
另:只差两个人了,一个姓陈,一个姓吴。
再另:姓陈的是陈水扁,姓吴的是吴淑珍。
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9335 | Accepted: 2325 |
Description
Input
Output
Sample Input
2 1
1 2 27
3 3
1 2 5
1 3 5
2 3 5
0 0
Sample Output
System #1
The last domino falls after 27.0 seconds, at key domino 2.
System #2
The last domino falls after 7.5 seconds, between key dominoes 2 and 3.
Source
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int const INF = 0x3fffffff; int const MAX = 505; int map[MAX][MAX]; int dis[MAX]; bool used[MAX]; int n, m, ca = 1; void Dijkstra(int v0) { memset(used, false, sizeof(used)); for(int i = 1; i <= n; i++) dis[i] = map[v0][i]; used[v0] = true; dis[v0] = 0; for(int i = 0; i < n - 1; i++) { int u = 1, mi = INF; for(int j = 1; j <= n; j++) { if(!used[j] && dis[j] < mi) { mi = dis[j]; u = j; } } used[u] = true; for(int k = 1; k <= n; k++) if(!used[k] && map[u][k] < INF) dis[k] = min(dis[k], dis[u] + map[u][k]); } double ma1 = -1, ma2 = -1; int pos, pos1, pos2; for(int i = 1; i <= n; i++) { if(dis[i] > ma1) { ma1 = dis[i]; pos = i; } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(map[i][j] < INF && (dis[i] + dis[j] + map[i][j]) / 2.0 > ma2) { ma2 = (dis[i] + dis[j] + map[i][j]) / 2.0; pos1 = i; pos2 = j; } } } if(ma1 < ma2) printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n\n", ma2, pos1, pos2); else printf("The last domino falls after %.1f seconds, at key domino %d.\n\n", ma1, pos); } int main() { while(scanf("%d %d", &n, &m) != EOF && (n + m)) { for(int i = 1; i <= n; i++) { dis[i] = INF; for(int j = 1; j <= n; j++) map[i][j] = INF; } for(int i = 0; i < m; i++) { int u, v, w; scanf("%d %d %d", &u, &v, &w); map[u][v] = w; map[v][u] = w; } printf("System #%d\n", ca ++); Dijkstra(1); } }
常见的存储区域可分为:
由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。
由new
分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new
就要对应一个delete
。如果程序员没有释放掉,程序会一直占用内存,导致内存泄漏,在程序结束后,操作系统会自动回收。
由malloc
等分配的内存块,它和堆是十分相似的,不过它是用free
来释放分配的内存。
全局变量和静态变量被分配到同一块内存中,在以前的C
语言中,全局变量又分为初始化的和未初始化的,在C++
里面没有这个区分了,他们共同占用同一块内存区。
这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改)。
例1:C
语言程序
int x;
void main()
{
}
变量x
存储在内存哪个区域?
答:在采用段式内存管理的架构中,BSS
段(bss segment
)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
BSS
是英文Block Started by Symbol
的简称。BSS
段属于静态存储区。
例2:static
全局变量与普通全局变量有什么区别?
答:static
全局变量和普通全局变量存储区域相同,不同的是:
static
全局变量只在声明此static
全局变量的文件中有效;
普通全局变量对整个源程序都有效,当此源程序包含多于一个文件的程序时,对其他文件依然有效。
例3:static
局部变量与普通局部变量的区别?
答:static
局部变量的存储区为静态存储区,普通局部变量的存储区为栈;
static
局部变量生存周期为整个源程序,但是只能在声明其的函数中调用,并且其值与上一次的结果有关;而普通局部变量的生存周期为声明其函数的周期,超过特定的范围其值会被重新初始化;
static
局部变量如果未初始化其值默认为0
,而普通局部变量则不确定。
//main.cpp
inta
= 0;//全局初始化区
char*p1;//全局未初始化区
main()
{
int b;//栈
char s[] = "abc";//栈
char * p2;//栈
char * p3 = "123456"; // 123456\0在常量区,p3在栈上。
static int c =0;//全局(静态)初始化区
p1 = (char*)malloc(10);
p2 = (char*)malloc(20);//分配得来的10和20字节的区域就在堆区。
}
1.内存分配方面:
堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS
回收。注意它与数据结构中的堆是两回事,分配方式是类似于链表。可能用到的关键字如下:new
、malloc
、delete
、free
等等。
栈:由编译器(Compiler
)自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2.申请方式方面:
堆:需要程序员自己申请,并指明大小。在c
中malloc
函数。如p1 = (char *)malloc(10);
在C++
中用new
运算符,但是注意p1
、p2
本身是在栈中的。因为他们还是可以认为是局部变量。
栈:由系统自动分配。 例如,声明在函数中一个局部变量 int b
;系统自动在栈中为b
开辟空间。
3.系统响应方面:
堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete
语句才能正确的释放本内存空间。另外由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中,由此可能会导致内存碎片。
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
4.大小限制方面:
堆:是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
栈:在Windows
下, 栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS
下,栈的大小是固定的(是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow
。因此,能从栈获得的空间较小。
5.效率方面:
堆:是由new
分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
栈:由系统自动分配,速度较快。但程序员是无法控制的。
6.存放内容方面:
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
栈:在函数调用时第一个进栈的是主函数中后的下一条指令(从函数返回的时候将继续从这条指令开始执行)(函数调用语句的下一条可执行语句)的地址然后是函数的各个参数,在大多数的C
编译器中,参数是由右往左入栈,然后是函数中的局部变量。注意:静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
7.存取效率方面:
堆:char *s1 = "Hellow Word"
;是在编译时就确定的;
栈:char s1[] = "Hellow Word"
;是在运行时赋值的;用数组比用指针速度要快一些,因为指针在底层汇编中需要用edx
寄存器中转一下,而数组在栈上直接读取。
有三种方法:
void swap1(int *a,int *b)//第一种,也是最常用的一种
{
int t;
t = *a;
*a = *b;
*b = t;
}
void swap2(int *a,int *b)//第二种,不需要额外的内存空间(不用临时变量)
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
//上述方法可能引起越界,为什么不使用他俩的差呢?
void newswap2( int *a, int *b)
{
*a = *b - *a;
*b = *b - *a;
*a = *a + *b;
}
//上述代码是用算术的过程来实现a与b的值的交换。这里主要的方法是考虑中间量|a-b|和留下一个原值。不过要使程序正确,还要做一些值的大小判断。写成函数的话会比较麻烦,通用性问题。
void swap3(int *a,int *b)//第三种,不需要额外的内存空间,位运算实现
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
//这里交换的方法也是依赖于公式A^B^A=B和A^B^B=A这个规律。但是函数参数的传递分为两种值传递和地址传递。故交换也有两种,值交换和变量所指向值的地址交换。只能交换整数(char int long),要想交换两个浮点数是不行的,因为浮点数不能参与位运算,要想交换两个指针也是不行的,编译器不允许你把两个指针拿来做位运算,要想交换两个用户自定义对象也是不行的,因为它仍然不能参与位运算
这种值交换的目的是为了减少临时变量的申请,减少程序所需的内存空间。对大量申请临时变量来实现交换的程序是一种很好的解决方案
- Normal equation
到目前为止,线性回归问题中都在使用梯度下降算法,但对于某些线性回归问题,正规方程方法是更好的解决方案。
正规方程就是通过求解如下方程来解析的找出使得代价函数最小的参数:
假设我们的训练集特征矩阵为X,我们的训练集结果为向量y,则利用正规方程解出向量:
以下表所示的数据为例:
运用正规方程方法求解参数为:
注意:对于那些不可逆的矩阵(通常是因为特征之间相互不独立,如同时包含英尺为单位的尺寸和米为单位的尺寸两个特征,或者是因为特征数量大于训练集的数量),正规方程的方法是不可用的。
梯度下降与正规方程的比较如下所示:
题目:
ACboy needs your help again! |
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
Total Submission(s): 73 Accepted Submission(s): 57 |
Problem Description ACboy was kidnapped!! he miss his mother very much and is very scare now.You can't image how dark the room he was put into is, so poor :(. As a smart ACMer, you want to get ACboy out of the monster's labyrinth.But when you arrive at the gate of the maze, the monste say :" I have heard that you are very clever, but if can't solve my problems, you will die with ACboy." The problems of the monster is shown on the wall: Each problem's first line is a integer N(the number of commands), and a word "FIFO" or "FILO".(you are very happy because you know "FIFO" stands for "First In First Out", and "FILO" means "First In Last Out"). and the following N lines, each line is "IN M" or "OUT", (M represent a integer). and the answer of a problem is a passowrd of a door, so if you want to rescue ACboy, answer the problem carefully! |
Input The input contains multiple test cases. The first line has one integer,represent the number oftest cases. And the input of each subproblem are described above. |
Output For each command "OUT", you should output a integer depend on the word is "FIFO" or "FILO", or a word "None" if you don't have any integer. |
Sample Input 4 4 FIFO IN 1 IN 2 OUT OUT 4 FILO IN 1 IN 2 OUT OUT 5 FIFO IN 1 IN 2 OUT OUT OUT 5 FILO IN 1 IN 2 OUT IN 3 OUT |
Sample Output 1 2 2 1 1 2 None 2 3 |
Source 2007省赛集训队练习赛(1) |
Recommend lcy |
题目分析:
栈和队列的基本使用,简单题。其实出题人的意思可能是让我们自己手写一个栈和队列。但是,作为一个早就知道STL的渣渣来说,是没有耐心再去写stack和queue了。。。哎哎。。
代码如下:
/* * a.cpp * 栈和队列的模拟 * * Created on: 2015年3月19日 * Author: Administrator */ #include <iostream> #include <cstdio> #include <stack> #include <queue> using namespace std; int main(){ int t; scanf("%d",&t); while(t--){ int n; string type; cin >> n >> type; if(type == "FIFO"){ queue<int> q; string cmd; int num; int i; for(i = 0 ; i < n ; ++i){ cin >> cmd; if(cmd == "IN"){ cin >> num; q.push(num); }else{ if(q.empty() == true){ printf("None\n"); }else{ int ans = q.front(); q.pop(); printf("%d\n",ans); } } } }else{ stack<int> st; string cmd; int num; int i; for(i = 0 ; i < n ; ++i){ cin >> cmd; if(cmd == "IN"){ cin >> num; st.push(num); }else{ if(st.empty() == true){ printf("None\n"); }else{ int ans = st.top(); st.pop(); printf("%d\n",ans); } } } } } return 0; }
一.事务
定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析。
二.ACID
ACID,是指在可靠数据库管理系统(DBMS)中,事务(transaction)所应该具有的四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability).这是可靠数据库所应具备的几个特性.下面针对这几个特性进行逐个讲解.
三.原子性
原子性是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。
1.案例
A给B转帐100元钱
2.分析
在事务中的扣款和加款两条语句,要么都执行,要么就都不执行。否则如果只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,在生活中就会引起纠纷。
3.解决方法
在数据库管理系统(DBMS)中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。保障事务的原子性是数据库管理系统的责任,为此许多数据源采用日志机制。例如,SQL Server使用一个预写事务日志,在将数据提交到实际数据页面前,先写在事务日志上。
四.一致性
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
1.案例
对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNT表中aaa和bbb的存款总额为2000元。
2.解决方法
保障事务的一致性,可以从以下两个层面入手
2.1数据库机制层面
数据库层面的一致性是,在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,Check约束等)和触发器设置。这一点是由SQL SERVER进行保证的。比如转账,则可以使用CHECK约束两个账户之和等于2000来达到一致性目的
2.2业务层面
对于业务层面来说,一致性是保持业务的一致性。这个业务一致性需要由开发人员进行保证。当然,很多业务方面的一致性,也可以通过转移到数据库机制层面进行保证。
五.隔离性
多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
这指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
在Windows中,如果多个进程对同一个文件进行修改是不允许的,Windows通过这种方式来保证不同进程的隔离性:
企业开发中,事务最复杂问题都是由事务隔离性引起的。当多个事务并发时,SQL Server利用加锁和阻塞来保证事务之间不同等级的隔离性。一般情况下,完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。想要理解SQL Server中对于隔离性的保障,首先要了解并发事务之间是如何干扰的.
1.事务之间的相互影响
事务之间的相互影响分为几种,分别为:脏读,不可重复读,幻读,丢失更新
1.1脏读
脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚的;如下案例,此时如果事务1回滚,则B账户必将有损失。
1.2不可重复读
不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。如下案例,事务1必然会变得糊涂,不知道发生了什么。
1.3幻读(虚读)
幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.
1.4丢失更新
两个事务同时读取同一条记录,A先修改记录,B也修改记录(B是不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。
2.理解SQL SERVER中的隔离级别
数据库的事务隔离级别(TRANSACTION ISOLATION LEVEL)是一个数据库上很基本的一个概念。为什么会有事务隔离级别,SQL Server上实现了哪些事务隔离级别?事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,我们引入了事务隔离级别这个概念,对一个单用户、单线程的应用来说则不存在这个问题。
为了避免上述几种事务之间的影响,SQL Server通过设置不同的隔离级别来进行不同程度的避免。因为高的隔离等级意味着更多的锁,从而牺牲性能。所以这个选项开放给了用户根据具体的需求进行设置。不过默认的隔离级别Read Commited符合了多数的实际需求.
隔离级别 |
脏读 |
丢失更新 |
不可重复读 |
幻读 |
并发模型 |
更新冲突检测 |
未提交读:Read Uncommited |
是 |
是 |
是 |
是 |
悲观 |
否 |
已提交读:Read commited |
否 |
是 |
是 |
是 |
悲观 |
否 |
可重复读:Repeatable Read |
否 |
否 |
否 |
是 |
悲观 |
否 |
可串行读:Serializable |
否 |
否 |
否 |
否 |
悲观 |
否 |
SQL Server隔离事务之间的影响是通过锁来实现的,通过阻塞来阻止上述影响。不同的隔离级别是通过加不同的锁,造成阻塞来实现的,所以会以付出性能作为代价;安全级别越高,处理效率越低;安全级别越低,效率高。
使用方法:SET TRANSACTIONISOLATION LEVEL REPEATABLE READ
未提交读: 在读数据时不会检查或使用任何锁。因此,在这种隔离级别中可能读取到没有提交的数据。
已提交读:只读取提交的数据并等待其他事务释放排他锁。读数据的共享锁在读操作完成后立即释放。已提交读是SQL Server的默认隔离级别。
可重复读: 像已提交读级别那样读数据,但会保持共享锁直到事务结束。
可串行读:工作方式类似于可重复读。但它不仅会锁定受影响的数据,还会锁定这个范围。这就阻止了新数据插入查询所涉及的范围。
六.持久性
持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
即使出现了任何事故比如断电等,事务一旦提交,则持久化保存在数据库中。
SQL SERVER通过write-ahead transaction log来保证持久性。write-ahead transaction log的意思是,事务中对数据库的改变在写入到数据库之前,首先写入到事务日志中。而事务日志是按照顺序排号的(LSN)。当数据库崩溃或者服务器断点时,重启动SQL SERVER,SQLSERVER首先会检查日志顺序号,将本应对数据库做更改而未做的部分持久化到数据库,从而保证了持久性。
七.总结
事务的(ACID)特性是由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
做上传图片功能,特别是类似于微信,QQ里面,发布9张图片, 少不了碰到一个问题,就是图片压缩问题,当然我也遇到了.
我研究了这个问题,发现网上普遍的方法是如下
我测试过上面方法,上面方法真不好用,真的不推荐大家用.那么我推荐下面这个方法:
上面这么长的东西,大家一定看的很费劲,那么我直接上我源码,给大家看看,照着我的源码,写就好了.
static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) {
ALAssetRepresentation *rep = (__bridge id)info;
NSError *error = nil;
size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];
if (countRead == 0 && error) {
// We have no way of passing this info back to the caller, so we log it, at least.
NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error);
}
return countRead;
}
static void releaseAssetCallback(void *info) {
// The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:.
// This release balances that retain.
CFRelease(info);
}
//压缩图片
- (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size
{
NSParameterAssert(asset != nil);
NSParameterAssert(size > 0);
ALAssetRepresentation *rep = [asset defaultRepresentation];
CGDataProviderDirectCallbacks callbacks =
{
.version = 0,
.getBytePointer = NULL,
.releaseBytePointer = NULL,
.getBytesAtPosition = getAssetBytesCallback,
.releaseInfo = releaseAssetCallback,
};
CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks);
CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef)
@{ (NSString *)kCGImageSourceCreateThumbnailFromImageAlways: @YES,
(NSString *)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithInt:size],
(NSString *)kCGImageSourceCreateThumbnailWithTransform :@YES,
});
CFRelease(source);
CFRelease(provider);
if (!imageRef) {
return nil;
}
UIImage *toReturn = [UIImage imageWithCGImage:imageRef];
CFRelease(imageRef);
return toReturn;
}
把上面的代码复制到工程里面,然后调用这个方法就好了,如下图:
好了,有问题,欢迎评论给我.....
本文部分内容参考自http://www.lyitnews.com/portal.php?mod=view&aid=1206,感谢他的分享....
有人问李华兄妹两个今年几岁了,李华说我们两个年龄之积是年龄之和的六倍,并且不是同一天出生,我肯定要比妹妹年龄大,且年龄相差不超过8
请你编写程序,输出李华妹妹的年龄。
分析:这道题刚开始做的时候的花了一个小时,也没做出来,就慌了,后来CTT告诉我就两层循环,就出来了;设李华的年龄为a,妹妹的年龄为b
分析的代码:
#include<iostream> #include<stdio.h> using namespace std; int main() { int a,b; for(int a=1;a<80;a++) { for(int b=1;b<80;b++) { if((a*b)/(a+b)==6&&a-b>0&&a-b<8) printf("%d %d\n",a,b); } } return 0; }从这个程序的结果找出合适的结果,可得a=15,b=10;符合条件
正确代码:
#include<iostream> #include<stdio.h> using namespace std; int main() { cout<<10<<endl; return 0; }
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6689 | Accepted: 2176 |
Description
Input
Output
Sample Input
0 0 10000 1000
0 200 5000 200 7000 200 -1 -1
2000 600 5000 600 10000 600 -1 -1
Sample Output
21
Source
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; int const MAX = 405; int const INF = 100000000.0; struct Node { double u, v; }nd[MAX]; double dis[MAX], e[MAX][MAX]; bool vis[MAX]; int cnt; double get_dis(double x1, double y1, double x2, double y2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } void Dijkstra(int v0) { for(int i = 0; i < cnt; i++) dis[i] = e[v0][i]; dis[v0] = 0; vis[v0] = true; for(int i = 0; i < cnt - 1; i++) { double mi = INF; int u = v0; for(int j = 0; j < cnt; j++) { if(!vis[j] && mi > dis[j]) { u = j; mi = dis[j]; } } vis[u] = true; for(int k = 0; k < cnt; k++) if(!vis[k] && dis[k] > dis[u] + e[u][k]) dis[k] = dis[u] + e[u][k]; } } int main() { memset(vis, false, sizeof(vis)); memset(e, 0, sizeof(e)); scanf("%lf %lf %lf %lf", &nd[0].u, &nd[0].v, &nd[1].u, &nd[1].v); double u, v; int tmp = 2; cnt = 2; while(scanf("%lf %lf", &u, &v) != EOF) { if(u == -1.0 && v == -1.0) { for(int i = tmp; i < cnt - 1; i++) { double get = get_dis(nd[i].u, nd[i].v, nd[i + 1].u, nd[i + 1].v) / 40000.0; e[i][i + 1] = e[i + 1][i] = get; } tmp = cnt; continue; } nd[cnt].u = u; nd[cnt++].v = v; } for(int i = 0; i < cnt; i++) for(int j = i + 1; j < cnt; j++) if(e[i][j] == 0) e[i][j] = e[j][i] = get_dis(nd[i].u, nd[i].v, nd[j].u, nd[j].v) / 10000.0; Dijkstra(0); printf("%d\n", (int)(dis[1] * 60.0 + 0.5)); }